import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
import type { User, MenuItem, UserOrgInfo } from '@/types'
import { apiClient } from '@/services/api'

interface AuthContextType {
  user: User | null
  token: string | null
  isAuthenticated: boolean
  isLoading: boolean
  login: (account: string, password: string) => Promise<void>
  loginWithToken: (token: string) => void
  logout: () => void
  currentOrg: { id: number; name: string } | null
  userOrgs: UserOrgInfo[]
  userMenus: MenuItem[]
  switchOrg: (orgId: number) => Promise<void>
  refreshMenus: () => Promise<void>
}

const AuthContext = createContext<AuthContextType | undefined>(undefined)

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null)
  const [token, setToken] = useState<string | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [currentOrg, setCurrentOrg] = useState<{ id: number; name: string } | null>(null)
  const [userOrgs, setUserOrgs] = useState<UserOrgInfo[]>([])
  const [userMenus, setUserMenus] = useState<MenuItem[]>([])

  useEffect(() => {
    const storedToken = localStorage.getItem('token')
    const storedUser = localStorage.getItem('user')

    if (storedToken) {
      setToken(storedToken)
    }

    if (storedUser) {
      try {
        setUser(JSON.parse(storedUser))
      } catch {
        localStorage.removeItem('user')
      }
    }

    const savedOrg = localStorage.getItem('currentOrg')
    if (savedOrg) {
      try { setCurrentOrg(JSON.parse(savedOrg)) } catch {}
    }

    setIsLoading(false)
  }, [])

  const refreshMenus = async () => {
    try {
      const data = await apiClient.getCurrentMenus()
      setUserMenus(data.list || [])
    } catch (e) {
      console.error('Failed to fetch menus:', e)
    }
  }

  const loadUserContext = async () => {
    try {
      const orgsData = await apiClient.getUserOrgs()
      const orgs = orgsData.list || []
      setUserOrgs(orgs)

      if (orgs.length > 0) {
        const storedOrg = localStorage.getItem('currentOrg')
        let selectedOrg = orgs[0]
        if (storedOrg) {
          try {
            const parsed = JSON.parse(storedOrg)
            const found = orgs.find((o: UserOrgInfo) => o.orgId === parsed.id)
            if (found) selectedOrg = found
          } catch {}
        }
        setCurrentOrg({ id: selectedOrg.orgId, name: selectedOrg.orgName })
        localStorage.setItem('currentOrg', JSON.stringify({ id: selectedOrg.orgId, name: selectedOrg.orgName }))
      }

      await refreshMenus()
    } catch (e) {
      console.error('Failed to load user context:', e)
      await refreshMenus()
    }
  }

  const switchOrgFn = async (orgId: number) => {
    try {
      const data = await apiClient.switchOrg(orgId)
      if (data.token) {
        localStorage.setItem('token', data.token)
        setToken(data.token)

        try {
          const payload = JSON.parse(atob(data.token.split('.')[1]))
          const userData: User = {
            id: payload.userId || 0,
            username: payload.username || '',
            email: '',
            role: payload.role || 'user',
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
          }
          setUser(userData)
          localStorage.setItem('user', JSON.stringify(userData))
        } catch {}

        const org = userOrgs.find((o: UserOrgInfo) => o.orgId === orgId)
        if (org) {
          setCurrentOrg({ id: org.orgId, name: org.orgName })
          localStorage.setItem('currentOrg', JSON.stringify({ id: org.orgId, name: org.orgName }))
        }

        await refreshMenus()
      }
    } catch (e) {
      console.error('Failed to switch org:', e)
      throw e
    }
  }

  useEffect(() => {
    if (token && !isLoading) {
      loadUserContext()
    }
  }, [token, isLoading])

  const login = async (account: string, password: string) => {
    try {
      const response = await apiClient.login({ account, password })

      if (response.success && response.token) {
        setToken(response.token)

        // 解析 JWT 获取用户信息
        try {
          const payload = JSON.parse(atob(response.token.split('.')[1]))
          const userData: User = {
            id: payload.userId || 0,
            username: payload.username || account,
            email: '',
            role: payload.role || 'user',
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
          }
          setUser(userData)
          localStorage.setItem('user', JSON.stringify(userData))
        } catch {
          const userData: User = {
            id: 0,
            username: account,
            email: '',
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
          }
          setUser(userData)
          localStorage.setItem('user', JSON.stringify(userData))
        }
      }
    } catch (error) {
      throw error
    }
  }

  const loginWithToken = (ssoToken: string) => {
    localStorage.setItem('token', ssoToken)
    setToken(ssoToken)

    // 解析 JWT 获取用户信息
    try {
      const payload = JSON.parse(atob(ssoToken.split('.')[1]))
      const userData: User = {
        id: payload.userId || 0,
        username: payload.username || '',
        email: payload.email || '',
        role: payload.role || 'user',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      }
      setUser(userData)
      localStorage.setItem('user', JSON.stringify(userData))
    } catch {
      // JWT 解析失败，使用占位数据
      const userData: User = {
        id: 0,
        username: 'SSO User',
        email: '',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString(),
      }
      setUser(userData)
      localStorage.setItem('user', JSON.stringify(userData))
    }
  }

  const logout = () => {
    apiClient.logout()
    setToken(null)
    setUser(null)
    setCurrentOrg(null)
    setUserOrgs([])
    setUserMenus([])
    localStorage.removeItem('user')
    localStorage.removeItem('currentOrg')
  }

  const value: AuthContextType = {
    user,
    token,
    isAuthenticated: !!token,
    isLoading,
    login,
    loginWithToken,
    logout,
    currentOrg,
    userOrgs,
    userMenus,
    switchOrg: switchOrgFn,
    refreshMenus,
  }

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}

export function useAuth() {
  const context = useContext(AuthContext)
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider')
  }
  return context
}
