"use client"

import { createContext, useContext, useState, useEffect, ReactNode } from "react"

export interface User {
  id: string
  email: string
  firstName: string
  lastName: string
  phone?: string
  avatarUrl?: string
  isVerified: boolean
  createdAt: string
}

interface AuthContextType {
  user: User | null
  isLoading: boolean
  isAuthenticated: boolean
  login: (email: string, password: string) => Promise<{ success: boolean; error?: string }>
  signup: (email: string, password: string) => Promise<{ success: boolean; error?: string }>
  logout: () => void
  verifyOTP: (email: string, otp: string) => Promise<{ success: boolean; error?: string }>
  resendOTP: (email: string) => Promise<{ success: boolean; error?: string }>
  requestPasswordReset: (email: string) => Promise<{ success: boolean; error?: string }>
  resetPassword: (email: string, otp: string, newPassword: string) => Promise<{ success: boolean; error?: string }>
  updateProfile: (data: Partial<User>) => Promise<{ success: boolean; error?: string }>
  pendingEmail: string | null
  setPendingEmail: (email: string | null) => void
  /** Demo only: get current OTP for display on verify page */
  getPendingOTP: (email: string) => string | null
}

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

// Mock user storage key
const USERS_KEY = "beachlyfe_users"
const CURRENT_USER_KEY = "beachlyfe_current_user"
const PENDING_OTPS_KEY = "beachlyfe_pending_otps"
const PENDING_EMAIL_KEY = "beachlyfe_pending_email"

// Helper to generate mock OTP
function generateOTP(): string {
  return Math.floor(100000 + Math.random() * 900000).toString()
}

// Helper to generate user ID
function generateUserId(): string {
  return `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [pendingEmail, setPendingEmailState] = useState<string | null>(null)
  const [, setOtpVersion] = useState(0)

  // Wrapper to persist pendingEmail to localStorage
  const setPendingEmail = (email: string | null) => {
    setPendingEmailState(email)
    if (email) {
      localStorage.setItem(PENDING_EMAIL_KEY, email)
    } else {
      localStorage.removeItem(PENDING_EMAIL_KEY)
    }
  }

  // Load user and pendingEmail from localStorage on mount
  useEffect(() => {
    const storedUser = localStorage.getItem(CURRENT_USER_KEY)
    if (storedUser) {
      try {
        setUser(JSON.parse(storedUser))
      } catch {
        localStorage.removeItem(CURRENT_USER_KEY)
      }
    }
    
    // Load pending email from storage
    const storedPendingEmail = localStorage.getItem(PENDING_EMAIL_KEY)
    if (storedPendingEmail) {
      setPendingEmailState(storedPendingEmail)
    }
    
    setIsLoading(false)
  }, [])

  // Get all users from storage
  const getUsers = (): Record<string, { password: string; user: User }> => {
    try {
      const users = localStorage.getItem(USERS_KEY)
      return users ? JSON.parse(users) : {}
    } catch {
      return {}
    }
  }

  // Save users to storage
  const saveUsers = (users: Record<string, { password: string; user: User }>) => {
    localStorage.setItem(USERS_KEY, JSON.stringify(users))
  }

  // Get pending OTPs
  const getOTPs = (): Record<string, { otp: string; expiresAt: number; type: "verify" | "reset" }> => {
    try {
      const otps = localStorage.getItem(PENDING_OTPS_KEY)
      return otps ? JSON.parse(otps) : {}
    } catch {
      return {}
    }
  }

  // Save OTPs
  const saveOTPs = (otps: Record<string, { otp: string; expiresAt: number; type: "verify" | "reset" }>) => {
    localStorage.setItem(PENDING_OTPS_KEY, JSON.stringify(otps))
  }

  const signup = async (email: string, password: string): Promise<{ success: boolean; error?: string }> => {
    // Simulate network delay
    await new Promise((resolve) => setTimeout(resolve, 800))

    const users = getUsers()
    if (users[email]) {
      return { success: false, error: "An account with this email already exists" }
    }

    // Create unverified user
    const newUser: User = {
      id: generateUserId(),
      email,
      firstName: "",
      lastName: "",
      isVerified: false,
      createdAt: new Date().toISOString(),
    }

    users[email] = { password, user: newUser }
    saveUsers(users)

    // Generate and store OTP
    const otp = generateOTP()
    const otps = getOTPs()
    otps[email] = {
      otp,
      expiresAt: Date.now() + 10 * 60 * 1000, // 10 minutes
      type: "verify",
    }
    saveOTPs(otps)
    setOtpVersion((v) => v + 1)
    console.log(`[BeachLyfe Demo] Verification OTP for ${email}: ${otp}`)
    setPendingEmail(email)
    return { success: true }
  }

  const verifyOTP = async (email: string, otp: string): Promise<{ success: boolean; error?: string }> => {
    await new Promise((resolve) => setTimeout(resolve, 500))

    const otps = getOTPs()
    const pending = otps[email]

    if (!pending) {
      return { success: false, error: "No verification code found. Please request a new one." }
    }

    if (Date.now() > pending.expiresAt) {
      delete otps[email]
      saveOTPs(otps)
      return { success: false, error: "Verification code has expired. Please request a new one." }
    }

    if (pending.otp !== otp) {
      return { success: false, error: "Invalid verification code. Please try again." }
    }

    // Mark user as verified
    const users = getUsers()
    if (users[email]) {
      users[email].user.isVerified = true
      // Auto-authenticate after successful verification so profile setup can persist.
      setUser(users[email].user)
      localStorage.setItem(CURRENT_USER_KEY, JSON.stringify(users[email].user))
      saveUsers(users)
    }

    // Clean up OTP
    delete otps[email]
    saveOTPs(otps)

    return { success: true }
  }

  const resendOTP = async (email: string): Promise<{ success: boolean; error?: string }> => {
    await new Promise((resolve) => setTimeout(resolve, 500))

    const users = getUsers()
    if (!users[email]) {
      return { success: false, error: "No account found with this email" }
    }

    const otp = generateOTP()
    const otps = getOTPs()
    otps[email] = {
      otp,
      expiresAt: Date.now() + 10 * 60 * 1000,
      type: "verify",
    }
    saveOTPs(otps)
    setOtpVersion((v) => v + 1)
    console.log(`[BeachLyfe Demo] New verification OTP for ${email}: ${otp}`)
    return { success: true }
  }

  const getPendingOTP = (email: string): string | null => {
    const otps = getOTPs()
    return otps[email]?.otp ?? null
  }

  const login = async (email: string, password: string): Promise<{ success: boolean; error?: string }> => {
    await new Promise((resolve) => setTimeout(resolve, 800))

    const users = getUsers()
    const userRecord = users[email]

    if (!userRecord) {
      return { success: false, error: "No account found with this email" }
    }

    if (userRecord.password !== password) {
      return { success: false, error: "Incorrect password" }
    }

    if (!userRecord.user.isVerified) {
      setPendingEmail(email)
      // Resend OTP for unverified users
      const otp = generateOTP()
      const otps = getOTPs()
      otps[email] = {
        otp,
        expiresAt: Date.now() + 10 * 60 * 1000,
        type: "verify",
      }
      saveOTPs(otps)
      console.log(`[BeachLyfe Demo] Verification OTP for ${email}: ${otp}`)
      return { success: false, error: "Please verify your email first" }
    }

    setUser(userRecord.user)
    localStorage.setItem(CURRENT_USER_KEY, JSON.stringify(userRecord.user))

    return { success: true }
  }

  const logout = () => {
    setUser(null)
    localStorage.removeItem(CURRENT_USER_KEY)
  }

  const requestPasswordReset = async (email: string): Promise<{ success: boolean; error?: string }> => {
    await new Promise((resolve) => setTimeout(resolve, 500))

    const users = getUsers()
    if (!users[email]) {
      // Don't reveal if email exists for security
      return { success: true }
    }

    const otp = generateOTP()
    const otps = getOTPs()
    otps[email] = {
      otp,
      expiresAt: Date.now() + 10 * 60 * 1000,
      type: "reset",
    }
    saveOTPs(otps)
    setOtpVersion((v) => v + 1)
    console.log(`[BeachLyfe Demo] Password reset OTP for ${email}: ${otp}`)
    setPendingEmail(email)

    return { success: true }
  }

  const resetPassword = async (
    email: string,
    otp: string,
    newPassword: string
  ): Promise<{ success: boolean; error?: string }> => {
    await new Promise((resolve) => setTimeout(resolve, 500))

    const otps = getOTPs()
    const pending = otps[email]

    if (!pending || pending.type !== "reset") {
      return { success: false, error: "No password reset request found" }
    }

    if (Date.now() > pending.expiresAt) {
      delete otps[email]
      saveOTPs(otps)
      return { success: false, error: "Reset code has expired. Please request a new one." }
    }

    if (pending.otp !== otp) {
      return { success: false, error: "Invalid reset code" }
    }

    // Update password
    const users = getUsers()
    if (users[email]) {
      users[email].password = newPassword
      saveUsers(users)
    }

    // Clean up
    delete otps[email]
    saveOTPs(otps)

    return { success: true }
  }

  const updateProfile = async (data: Partial<User>): Promise<{ success: boolean; error?: string }> => {
    await new Promise((resolve) => setTimeout(resolve, 500))

    if (!user) {
      return { success: false, error: "Not authenticated" }
    }

    const updatedUser = { ...user, ...data }
    setUser(updatedUser)
    localStorage.setItem(CURRENT_USER_KEY, JSON.stringify(updatedUser))

    // Also update in users storage
    const users = getUsers()
    if (users[user.email]) {
      users[user.email].user = updatedUser
      saveUsers(users)
    }

    return { success: true }
  }

  return (
    <AuthContext.Provider
      value={{
        user,
        isLoading,
        isAuthenticated: !!user,
        login,
        signup,
        logout,
        verifyOTP,
        resendOTP,
        requestPasswordReset,
        resetPassword,
        updateProfile,
        pendingEmail,
        setPendingEmail,
        getPendingOTP,
      }}
    >
      {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
}
