import { createContext, useContext, useEffect, useState, useCallback, type ReactNode } from "react"
import { useNavigate } from "react-router-dom"
import { adminLogin, adminLogout, adminMe } from "../api/auth"
import { ADMIN_ACCESS_KEY, ADMIN_REFRESH_KEY } from "../api/client"
import type { User } from "../../types"
import type { CaptchaResult } from "../../utils/geetest"

type Captcha = CaptchaResult | null

interface AdminAuthContextType {
  admin: User | null
  isLoading: boolean
  login: (account: string, password: string, captcha: Captcha) => Promise<void>
  logout: () => Promise<void>
  setAdmin: (user: User) => void
}

const AdminAuthContext = createContext<AdminAuthContextType | undefined>(undefined)

export function AdminAuthProvider({ children }: { children: ReactNode }) {
  const [admin, setAdmin] = useState<User | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const navigate = useNavigate()

  const loadAdmin = useCallback(async () => {
    try {
      const accessToken = localStorage.getItem(ADMIN_ACCESS_KEY)
      const refreshToken = localStorage.getItem(ADMIN_REFRESH_KEY)
      if (!accessToken && !refreshToken) {
        setIsLoading(false)
        return
      }
      const res = await adminMe()
      if (res.data) setAdmin(res.data)
    } catch {
      localStorage.removeItem(ADMIN_ACCESS_KEY)
      localStorage.removeItem(ADMIN_REFRESH_KEY)
    } finally {
      setIsLoading(false)
    }
  }, [])

  useEffect(() => {
    loadAdmin()
  }, [loadAdmin])

  useEffect(() => {
    const onUnauthorized = () => {
      setAdmin(null)
      navigate("/admin/login", { replace: true })
    }
    window.addEventListener("admin:unauthorized", onUnauthorized)
    return () => window.removeEventListener("admin:unauthorized", onUnauthorized)
  }, [navigate])

  const login = async (account: string, password: string, captcha: Captcha) => {
    const res = await adminLogin(account, password, captcha)
    if (res.data) {
      localStorage.setItem(ADMIN_ACCESS_KEY, res.data.tokens.access_token)
      localStorage.setItem(ADMIN_REFRESH_KEY, res.data.tokens.refresh_token)
      setAdmin(res.data.user)
      navigate("/admin")
    }
  }

  const logout = async () => {
    const refreshToken = localStorage.getItem(ADMIN_REFRESH_KEY)
    try {
      if (refreshToken) await adminLogout(refreshToken)
    } catch {
      // ignore
    }
    localStorage.removeItem(ADMIN_ACCESS_KEY)
    localStorage.removeItem(ADMIN_REFRESH_KEY)
    setAdmin(null)
    navigate("/admin/login", { replace: true })
  }

  return (
    <AdminAuthContext.Provider value={{ admin, isLoading, login, logout, setAdmin }}>
      {children}
    </AdminAuthContext.Provider>
  )
}

export function useAdminAuth() {
  const ctx = useContext(AdminAuthContext)
  if (!ctx) throw new Error("useAdminAuth must be used within an AdminAuthProvider")
  return ctx
}
