'use client'

// React Imports
import { createContext, useContext, useEffect, useState, ReactNode } from 'react'

// API Imports
import { authService, type AuthUser } from '@/libs/api/services/authService'

export type LoginResult = { user: AuthUser | null }

interface AuthContextType {
  user: AuthUser | null
  isLoading: boolean
  isAuthenticated: boolean
  login: (phoneNumber: string, otpCode: string, tempToken: string) => Promise<LoginResult>
  requestOTP: (phoneNumber: string) => Promise<string>
  logout: () => void
}

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

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

interface AuthProviderProps {
  children: ReactNode
}

const STORAGE_KEYS = {
  authUser: 'auth_user',
  authToken: 'auth_token'
} as const

export const AuthProvider = ({ children }: AuthProviderProps) => {
  const [user, setUser] = useState<AuthUser | null>(null)
  const [isLoading, setIsLoading] = useState(true)

  // Check if user is authenticated on mount
  useEffect(() => {
    // Check for stored token and user data
    const token =
      typeof window !== 'undefined' ? localStorage.getItem(STORAGE_KEYS.authToken) : null
    const storedUser =
      typeof window !== 'undefined' ? localStorage.getItem(STORAGE_KEYS.authUser) : null

    if (token && storedUser) {
      try {
        const userData = JSON.parse(storedUser)
        setUser(userData)
      } catch (error) {
        console.error('Error parsing stored user data:', error)
        // Clear invalid data
        localStorage.removeItem(STORAGE_KEYS.authToken)
        localStorage.removeItem(STORAGE_KEYS.authUser)
      }
    }
    setIsLoading(false)
  }, [])

  const requestOTP = async (phoneNumber: string): Promise<string> => {
    const response = await authService.requestOTP(phoneNumber)
    if (response.code === 200) {
      return response.token // Return temp token for OTP verification
    }
    throw new Error(response.msg || 'Failed to request OTP')
  }

  /**
   * Normalize API user object to AuthUser (handles data vs user key and snake_case vs camelCase).
   */
  const normalizeUser = (raw: Record<string, unknown> | null | undefined): AuthUser => {
    if (!raw || typeof raw !== 'object') {
      return {
        id: 0,
        username: '',
        email: '',
        first_name: '',
        last_name: '',
        phone_number: ''
      }
    }
    const first = (raw.first_name as string) ?? (raw.firstName as string) ?? ''
    const last = (raw.last_name as string) ?? (raw.lastName as string) ?? ''
    return {
      id: Number(raw.id) || 0,
      username: (raw.username as string) ?? '',
      email: (raw.email as string) ?? '',
      first_name: first,
      last_name: last,
      phone_number: (raw.phone_number as string) ?? (raw.phoneNumber as string) ?? ''
    }
  }

  const login = async (phoneNumber: string, otpCode: string, tempToken: string): Promise<LoginResult> => {
    const response = await authService.verifyOTP(tempToken, otpCode) as {
      code: number
      msg?: string
      data?: AuthUser | Record<string, unknown>
      user?: AuthUser | Record<string, unknown>
      token?: string
    }

    if (response.code !== 200 || !response.token) {
      throw new Error(response.msg || 'OTP verification failed')
    }

    const rawUser = response.data ?? response.user
    const partialUserRaw =
      rawUser && typeof rawUser === 'object' && rawUser !== null
        ? (rawUser as Record<string, unknown>)
        : undefined

    const userData: AuthUser = partialUserRaw
      ? normalizeUser(partialUserRaw)
      : normalizeUser(undefined)
    setUser(userData)
    if (typeof window !== 'undefined') {
      localStorage.setItem(STORAGE_KEYS.authUser, JSON.stringify(userData))
    }
    return { user: userData }
  }

  const logout = () => {
    authService.logout()
    setUser(null)
    if (typeof window !== 'undefined') {
      localStorage.removeItem(STORAGE_KEYS.authUser)
    }
  }

  const value: AuthContextType = {
    user,
    isLoading,
    isAuthenticated: !!user,
    login,
    requestOTP,
    logout
  }

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

