import { toast } from '../main'
import { setToken, loadCurrentUser } from './auth'
import { registerPush } from './push'

function generateCodeVerifier() {
  const array = new Uint8Array(32)
  window.crypto.getRandomValues(array)
  return Array.from(array)
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('')
}

async function generateCodeChallenge(codeVerifier) {
  const encoder = new TextEncoder()
  const data = encoder.encode(codeVerifier)
  const digest = await window.crypto.subtle.digest('SHA-256', data)
  return btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '')
}

// 邀请码明文放入 state；同时生成 csrf 放入 state 并在回调校验
export async function twitterAuthorize(inviteToken = '') {
  const config = useRuntimeConfig()
  const WEBSITE_BASE_URL = config.public.websiteBaseUrl
  const TWITTER_CLIENT_ID = config.public.twitterClientId
  if (!TWITTER_CLIENT_ID) {
    toast.error('Twitter 登录不可用')
    return
  }

  const redirectUri = `${WEBSITE_BASE_URL}/twitter-callback`

  // PKCE
  const codeVerifier = generateCodeVerifier()
  sessionStorage.setItem('twitter_code_verifier', codeVerifier)
  const codeChallenge = await generateCodeChallenge(codeVerifier)

  // CSRF + 邀请码一起放入 state
  const csrf = Math.random().toString(36).slice(2)
  sessionStorage.setItem('twitter_csrf_state', csrf)
  const state = new URLSearchParams({
    csrf,
    invite_token: inviteToken || '',
  }).toString()

  const url =
    `https://x.com/i/oauth2/authorize?response_type=code&client_id=${encodeURIComponent(TWITTER_CLIENT_ID)}` +
    `&redirect_uri=${encodeURIComponent(redirectUri)}` +
    `&scope=${encodeURIComponent('tweet.read users.read')}` +
    `&state=${encodeURIComponent(state)}` +
    `&code_challenge=${encodeURIComponent(codeChallenge)}` +
    `&code_challenge_method=S256`

  window.location.href = url
}

export async function twitterExchange(code, state, reason) {
  try {
    const config = useRuntimeConfig()
    const API_BASE_URL = config.public.apiBaseUrl

    // 取出并清理 PKCE/CSRF
    const codeVerifier = sessionStorage.getItem('twitter_code_verifier')
    sessionStorage.removeItem('twitter_code_verifier')

    const savedCsrf = sessionStorage.getItem('twitter_csrf_state')
    sessionStorage.removeItem('twitter_csrf_state')

    // 从 state 解析 csrf 与 invite_token
    let parsedCsrf = ''
    let inviteToken = ''
    try {
      const sp = new URLSearchParams(state || '')
      parsedCsrf = sp.get('csrf') || ''
      inviteToken = sp.get('invite_token') || sp.get('invitetoken') || ''
    } catch {}

    // 简单 CSRF 校验（存在才校验，避免误杀老会话）
    if (savedCsrf && parsedCsrf && savedCsrf !== parsedCsrf) {
      toast.error('登录状态校验失败，请重试')
      return { success: false, needReason: false, error: 'state mismatch' }
    }

    const res = await fetch(`${API_BASE_URL}/api/auth/twitter`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        code,
        redirectUri: `${window.location.origin}/twitter-callback`,
        reason,
        state,
        codeVerifier,
        inviteToken,
      }),
    })

    const data = await res.json()
    if (res.ok && data.token) {
      setToken(data.token)
      await loadCurrentUser()
      toast.success('登录成功')
      registerPush()
      return { success: true, needReason: false }
    } else if (data.reason_code === 'NOT_APPROVED') {
      toast.info('当前为注册审核模式，请填写注册理由')
      return { success: false, needReason: true, token: data.token }
    } else if (data.reason_code === 'IS_APPROVING') {
      toast.info('您的注册理由正在审批中')
      return { success: true, needReason: false }
    } else {
      toast.error(data.error || '登录失败')
      return { success: false, needReason: false, error: data.error || '登录失败' }
    }
  } catch (e) {
    console.error(e)
    toast.error('登录失败')
    return { success: false, needReason: false, error: '登录失败' }
  }
}
