"use client"

import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from "react"
import * as api from "./api"
import type { User } from "./types"

interface AuthContextValue {
  user: User | null
  loading: boolean
  login: (username: string, password: string) => Promise<void>
  register: (username: string, password: string, email: string) => Promise<void>
  logout: () => void
  refreshUser: () => Promise<void>
}

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

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null)
  const [loading, setLoading] = useState(true)

  const loadUser = useCallback(async () => {
    if (!api.getToken()) {
      setUser(null)
      setLoading(false)
      return
    }
    try {
      const me = await api.getMe()
      setUser(me)
    } catch {
      api.clearToken()
      setUser(null)
    } finally {
      setLoading(false)
    }
  }, [])

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

  const login = useCallback(async (username: string, password: string) => {
    await api.login(username, password)
    const me = await api.getMe()
    setUser(me)
  }, [])

  const register = useCallback(
    async (username: string, password: string, email: string) => {
      await api.register(username, password, email)
      // Backend requires email verification, but login works immediately.
      await api.login(username, password)
      const me = await api.getMe()
      setUser(me)
    },
    [],
  )

  const logout = useCallback(() => {
    api.clearToken()
    setUser(null)
  }, [])

  const refreshUser = useCallback(async () => {
    const me = await api.getMe()
    setUser(me)
  }, [])

  return (
    <AuthContext.Provider value={{ user, loading, login, register, logout, refreshUser }}>
      {children}
    </AuthContext.Provider>
  )
}

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