import { useState, useEffect, useCallback } from 'react'
import type { User } from '@supabase/supabase-js'
import { getSupabase } from '../lib/supabase'
import type { AuthUser } from '../types'

export type { AuthUser }

interface UseAuthReturn {
  /** Current authenticated user or null. */
  user: AuthUser | null
  /** Loading state during auth operations. */
  loading: boolean
  /** Error message if any. */
  error: string | null
  /** Whether user is authenticated. */
  isAuthenticated: boolean
  /** Create a new account with email and password. */
  signUp: (email: string, password: string, displayName?: string) => Promise<boolean>
  /** Sign in with email and password. */
  signIn: (email: string, password: string) => Promise<boolean>
  /** Sign out the current user. */
  signOut: () => Promise<boolean>
  /** Send password reset email. */
  resetPassword: (email: string) => Promise<boolean>
  /** Clear current error. */
  clearError: () => void
}

/** Map a Supabase User to the AuthUser shape. */
function mapUser(user: User | null | undefined): AuthUser | null {
  if (!user) return null
  return { id: user.id, email: user.email ?? null }
}

/**
 * Hook for Supabase Authentication with email/password.
 * Subscribes to auth state changes; unsubscribes on unmount.
 * When Supabase is not configured, methods return a clear error (no crash).
 */
export function useAuth(): UseAuthReturn {
  const [user, setUser] = useState<AuthUser | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    const client = getSupabase()
    if (!client) {
      setLoading(false)
      setError('Supabase Auth not initialized. Make sure to call initSupabase() first.')
      return
    }

    let mounted = true

    client.auth
      .getSession()
      .then(({ data }: any) => {
        if (!mounted) return
        setUser(mapUser(data?.session?.user))
        setLoading(false)
      })
      .catch(() => {
        if (mounted) setLoading(false)
      })

    const { data } = client.auth.onAuthStateChange((_event: string, session: any) => {
      if (!mounted) return
      setUser(mapUser(session?.user))
      setLoading(false)
    })

    return () => {
      mounted = false
      data?.subscription?.unsubscribe?.()
    }
  }, [])

  const signUp = useCallback(
    async (email: string, password: string, _displayName?: string): Promise<boolean> => {
      const client = getSupabase()
      if (!client) {
        setError('Supabase Auth not initialized')
        return false
      }
      try {
        setError(null)
        const { error: err } = await client.auth.signUp({ email, password })
        if (err) {
          setError(err.message || 'Sign up failed')
          return false
        }
        return true
      } catch (e) {
        setError(e instanceof Error ? e.message : 'Sign up failed')
        return false
      }
    },
    []
  )

  const signIn = useCallback(async (email: string, password: string): Promise<boolean> => {
    const client = getSupabase()
    if (!client) {
      setError('Supabase Auth not initialized')
      return false
    }
    try {
      setError(null)
      const { error: err } = await client.auth.signInWithPassword({ email, password })
      if (err) {
        setError(err.message || 'Sign in failed')
        return false
      }
      return true
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Sign in failed')
      return false
    }
  }, [])

  const signOut = useCallback(async (): Promise<boolean> => {
    const client = getSupabase()
    if (!client) {
      setError('Supabase Auth not initialized')
      return false
    }
    try {
      setError(null)
      const { error: err } = await client.auth.signOut()
      if (err) {
        setError(err.message || 'Sign out failed')
        return false
      }
      return true
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Sign out failed')
      return false
    }
  }, [])

  const resetPassword = useCallback(async (email: string): Promise<boolean> => {
    const client = getSupabase()
    if (!client) {
      setError('Supabase Auth not initialized')
      return false
    }
    try {
      setError(null)
      const { error: err } = await client.auth.resetPasswordForEmail(email)
      if (err) {
        setError(err.message || 'Password reset failed')
        return false
      }
      return true
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Password reset failed')
      return false
    }
  }, [])

  const clearError = useCallback(() => {
    setError(null)
  }, [])

  return {
    user,
    loading,
    error,
    isAuthenticated: !!user,
    signUp,
    signIn,
    signOut,
    resetPassword,
    clearError,
  }
}
