import { createContext, useContext, useState, useEffect, ReactNode, useCallback } from 'react'
import { authApi, TokenResponse } from '../api/auth'
import { UserRoleValue } from '../api/users'

interface AuthState {
  isAuthenticated: boolean
  username: string | null
  isLoading: boolean
  passwordChangeRequired: boolean
  isAdmin: boolean
  role: UserRoleValue | null
  permissions: Record<string, boolean>
}

interface AuthContextType extends AuthState {
  login: (username: string, password: string) => Promise<{ success: boolean; error?: string; passwordChangeRequired?: boolean }>
  logout: () => void
  clearPasswordChangeRequired: () => void
  hasPermission: (featureKey: string) => boolean
}

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

export function AuthProvider({ children }: { children: ReactNode }) {
  const [authState, setAuthState] = useState<AuthState>({
    isAuthenticated: false,
    username: null,
    isLoading: true,
    passwordChangeRequired: false,
    isAdmin: false,
    role: null,
    permissions: {},
  })

  useEffect(() => {
    const token = localStorage.getItem('access_token')
    if (token) {
      authApi
        .me()
        .then((user) => {
          setAuthState({
            isAuthenticated: true,
            username: user.username,
            isLoading: false,
            passwordChangeRequired: false,
            isAdmin: user.is_admin || false,
            role: (user.role as UserRoleValue) || null,
            permissions: user.permissions || {},
          })
        })
        .catch(() => {
          localStorage.removeItem('access_token')
          localStorage.removeItem('refresh_token')
          setAuthState({
            isAuthenticated: false,
            username: null,
            isLoading: false,
            passwordChangeRequired: false,
            isAdmin: false,
            role: null,
            permissions: {},
          })
        })
    } else {
      setAuthState({
        isAuthenticated: false,
        username: null,
        isLoading: false,
        passwordChangeRequired: false,
        isAdmin: false,
        role: null,
        permissions: {},
      })
    }
  }, [])

  const login = async (username: string, password: string) => {
    try {
      setAuthState((prev) => ({ ...prev, isLoading: true }))
      const tokens: TokenResponse = await authApi.login({ username, password })
      localStorage.setItem('access_token', tokens.access_token)
      localStorage.setItem('refresh_token', tokens.refresh_token)
      const user = await authApi.me()
      const passwordChangeRequired = tokens.password_change_required || false
      setAuthState({
        isAuthenticated: true,
        username: user.username,
        isLoading: false,
        passwordChangeRequired,
        isAdmin: user.is_admin || false,
        role: (user.role as UserRoleValue) || null,
        permissions: user.permissions || {},
      })
      return { success: true, passwordChangeRequired }
    } catch (error: any) {
      setAuthState((prev) => ({ ...prev, isLoading: false }))
      console.error('Login error:', error)
      return {
        success: false,
        error: error.response?.data?.detail || error.message || 'Login failed',
      }
    }
  }

  const clearPasswordChangeRequired = () => {
    setAuthState((prev) => ({
      ...prev,
      passwordChangeRequired: false,
    }))
  }

  const logout = () => {
    localStorage.removeItem('access_token')
    localStorage.removeItem('refresh_token')
    // Clear sessionStorage settings on logout
    sessionStorage.removeItem('identify_settings')
    setAuthState({
      isAuthenticated: false,
      username: null,
      isLoading: false,
      passwordChangeRequired: false,
      isAdmin: false,
      role: null,
      permissions: {},
    })
  }

  const hasPermission = useCallback(
    (featureKey: string): boolean => {
      if (!featureKey) {
        return authState.isAdmin
      }
      if (authState.isAdmin) {
        return true
      }
      return Boolean(authState.permissions[featureKey])
    },
    [authState.isAdmin, authState.permissions]
  )

  return (
    <AuthContext.Provider value={{ ...authState, login, logout, clearPasswordChangeRequired, hasPermission }}>
      {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
}

