import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
import { api, TOKEN_KEY, REFRESH_KEY, USER_KEY } from '@/lib/api'
import type { AuthResponse, LoginPayload, UserInfo } from '@/types/auth'
import type { MenuNode } from '@/types/menu'

type AuthContextValue = {
  user: UserInfo | null
  menu: MenuNode[]
  isAuthenticated: boolean
  isBootstrapping: boolean
  login: (payload: LoginPayload) => Promise<void>
  logout: () => void
  refreshMenu: () => Promise<void>
}

const AuthContext = createContext<AuthContextValue | null>(null)
const MENU_KEY = 'solution-erp-user-menu'

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<UserInfo | null>(null)
  const [menu, setMenu] = useState<MenuNode[]>([])
  const [isBootstrapping, setIsBootstrapping] = useState(true)

  async function loadMenu() {
    try {
      const res = await api.get<MenuNode[]>('/menus/me')
      setMenu(res.data)
      localStorage.setItem(MENU_KEY, JSON.stringify(res.data))
    } catch {
      // keep cached
    }
  }

  useEffect(() => {
    const token = localStorage.getItem(TOKEN_KEY)
    const userRaw = localStorage.getItem(USER_KEY)
    const menuRaw = localStorage.getItem(MENU_KEY)
    if (token && userRaw) {
      try {
        setUser(JSON.parse(userRaw))
        if (menuRaw) setMenu(JSON.parse(menuRaw))
        loadMenu()
      } catch {
        localStorage.removeItem(USER_KEY)
        localStorage.removeItem(MENU_KEY)
      }
    }
    setIsBootstrapping(false)
  }, [])

  async function login(payload: LoginPayload) {
    const res = await api.post<AuthResponse>('/auth/login', payload)
    localStorage.setItem(TOKEN_KEY, res.data.accessToken)
    localStorage.setItem(REFRESH_KEY, res.data.refreshToken)
    localStorage.setItem(USER_KEY, JSON.stringify(res.data.user))
    setUser(res.data.user)
    await loadMenu()
  }

  function logout() {
    localStorage.removeItem(TOKEN_KEY)
    localStorage.removeItem(REFRESH_KEY)
    localStorage.removeItem(USER_KEY)
    localStorage.removeItem(MENU_KEY)
    setUser(null)
    setMenu([])
    // Close realtime socket — avoid leaking auth'd connection across users
    import('@/lib/realtime').then(m => m.stopConnection()).catch(() => {})
  }

  return (
    <AuthContext.Provider value={{ user, menu, isAuthenticated: !!user, isBootstrapping, login, logout, refreshMenu: loadMenu }}>
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth() {
  const ctx = useContext(AuthContext)
  if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
  return ctx
}
