'use client'
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react'

export interface User {
  id: string
  email: string
  name: string
  role: 'user' | 'admin'
  avatar?: string
  isVerified: boolean
  provider: string
  createdAt: string
  updatedAt: string
  siliconId?: string
  balance?: number
}

interface AuthContextType {
  user: User | null
  balance: number | null
  loading: boolean
  error: string | null
  login: (emailOrId: string, password: string, rememberMe?: boolean) => Promise<void>
  register: (email: string, name: string, password: string) => Promise<void>
  logout: () => Promise<void>
  refreshUser: () => Promise<void>
  checkAuth: () => Promise<void>
  getBalance: () => Promise<number>
  addBalance: (
    amount: number,
    currency: 'INR' | 'USD'
  ) => Promise<{ success: boolean; paymentUrl?: string; formData?: any; error?: string }>
  refreshBalance: () => Promise<void>
}

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

interface AuthProviderProps {
  children: ReactNode
}

export function AuthProvider({ children }: AuthProviderProps) {
  const [user, setUser] = useState<User | null>(null)
  const [balance, setBalance] = useState<number | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [hasCheckedAuth, setHasCheckedAuth] = useState(false)

  // API call helper
  const apiCall = async (endpoint: string, options: RequestInit = {}) => {
    const response = await fetch(`/api/auth${endpoint}`, {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
      credentials: 'include', // Include cookies
      ...options,
    })

    const data = await response.json()

    if (!data.success) {
      throw new Error(data.error?.message || 'An error occurred')
    }

    return data
  }

  // Balance API call helper
  const balanceApiCall = async (endpoint: string, options: RequestInit = {}) => {
    const response = await fetch(`/api${endpoint}`, {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
      credentials: 'include',
      ...options,
    })

    const data = await response.json()
    return data
  }

  // Check if user is authenticated - only when explicitly needed
  const checkAuth = async () => {
    // Skip if already checked in this session or if user is already set
    if (hasCheckedAuth || user) {
      setLoading(false)
      return
    }

    try {
      setLoading(true)
      setError(null)

      const data = await apiCall('/me')
      setUser(data.data.user)
      setBalance(data.data.user.balance || null)
      setHasCheckedAuth(true)
    } catch (err) {
      // If getting user info fails, try to refresh token
      try {
        const refreshData = await apiCall('/refresh', { method: 'POST' })
        setUser(refreshData.data.user)
        setBalance(refreshData.data.user.balance || null)
        setHasCheckedAuth(true)
      } catch (refreshErr) {
        // Both failed, user is not authenticated
        setUser(null)
        setBalance(null)
        setHasCheckedAuth(true)
      }
    } finally {
      setLoading(false)
    }
  }

  // Login function
  const login = async (emailOrId: string, password: string, rememberMe?: boolean) => {
    try {
      setLoading(true)
      setError(null)

      const data = await apiCall('/login', {
        method: 'POST',
        body: JSON.stringify({ emailOrId, password, rememberMe }),
      })

      setUser(data.data.user)
      setBalance(data.data.user.balance || null)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Login failed')
      throw err
    } finally {
      setLoading(false)
    }
  }

  // Register function
  const register = async (email: string, name: string, password: string) => {
    try {
      setLoading(true)
      setError(null)

      const data = await apiCall('/register', {
        method: 'POST',
        body: JSON.stringify({ email, name, password }),
      })

      setUser(data.data.user)
      setBalance(data.data.user.balance || null)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Registration failed')
      throw err
    } finally {
      setLoading(false)
    }
  }

  // Logout function
  const logout = async () => {
    try {
      setLoading(true)
      await apiCall('/logout', { method: 'POST' })
      setUser(null)
      setBalance(null)
    } catch (err) {
      console.error('Logout error:', err)
      // Even if logout API fails, clear user state
      setUser(null)
      setBalance(null)
    } finally {
      setLoading(false)
    }
  }

  // Refresh user data
  const refreshUser = async () => {
    try {
      const data = await apiCall('/me')
      setUser(data.data.user)
      setBalance(data.data.user.balance || null)
    } catch (err) {
      console.error('Refresh user error:', err)
      setUser(null)
      setBalance(null)
    }
  }

  // Get user balance
  const getBalance = async (): Promise<number> => {
    try {
      const data = await balanceApiCall('/user/balance')
      if (data.success) {
        return data.data.balance
      }
      throw new Error(data.error?.message || 'Failed to fetch balance')
    } catch (err) {
      console.error('Get balance error:', err)
      throw err
    }
  }

  // Add balance (initiate payment)
  const addBalance = async (amount: number, currency: 'INR' | 'USD' = 'INR') => {
    try {
      const data = await balanceApiCall('/balance/add', {
        method: 'POST',
        body: JSON.stringify({ amount, currency }),
      })

      if (data.success) {
        return {
          success: true,
          paymentUrl: data.payment_url,
          formData: data.form_data,
        }
      } else {
        return {
          success: false,
          error: data.message || 'Failed to initiate payment',
        }
      }
    } catch (err) {
      console.error('Add balance error:', err)
      return {
        success: false,
        error: err instanceof Error ? err.message : 'Failed to add balance',
      }
    }
  }

  // Refresh balance and update user state
  const refreshBalance = async () => {
    try {
      const newBalance = await getBalance()
      setBalance(newBalance)
      if (user) {
        setUser({ ...user, balance: newBalance })
      }
    } catch (err) {
      console.error('Refresh balance error:', err)
    }
  }

  // Check for existing session on mount (restore user state)
  useEffect(() => {
    const restoreSession = async () => {
      try {
        setLoading(true)
        const data = await apiCall('/me')
        setUser(data.data.user)
        setBalance(data.data.user.balance || null)
        setHasCheckedAuth(true)
      } catch (err) {
        // If /me fails, try refresh token
        try {
          const refreshData = await apiCall('/refresh', { method: 'POST' })
          setUser(refreshData.data.user)
          setBalance(refreshData.data.user.balance || null)
          setHasCheckedAuth(true)
        } catch (refreshErr) {
          // No valid session
          setUser(null)
          setBalance(null)
          setHasCheckedAuth(true)
        }
      } finally {
        setLoading(false)
      }
    }

    restoreSession()
  }, [])

  // Set up auto-refresh only when user is logged in
  useEffect(() => {
    if (!user) return

    // Auto-refresh user data when tab becomes visible (after 5+ minutes)
    let lastRefresh = Date.now()
    const handleVisibilityChange = () => {
      if (!document.hidden && Date.now() - lastRefresh > 5 * 60 * 1000) {
        refreshUser()
        lastRefresh = Date.now()
      }
    }

    document.addEventListener('visibilitychange', handleVisibilityChange)
    return () => document.removeEventListener('visibilitychange', handleVisibilityChange)
  }, [user])

  // Auto-refresh token every 10 minutes if user is logged in
  useEffect(() => {
    if (!user) return

    const interval = setInterval(
      async () => {
        try {
          await apiCall('/refresh', { method: 'POST' })
        } catch (err) {
          console.error('Auto-refresh failed:', err)
          setUser(null) // Log out if refresh fails
          setBalance(null)
        }
      },
      10 * 60 * 1000
    ) // 10 minutes

    return () => clearInterval(interval)
  }, [user])

  const value: AuthContextType = {
    user,
    balance,
    loading,
    error,
    login,
    register,
    logout,
    refreshUser,
    checkAuth,
    getBalance,
    addBalance,
    refreshBalance,
  }

  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
}
