import { supabase } from '@/utils/supabase/supabase'
import { AppState, AppStateStatus } from 'react-native'

import type { Session, User } from '@supabase/supabase-js'
import { createContext, useContext, useEffect, useMemo, useState } from 'react'

// Tells Supabase Auth to continuously refresh the session automatically if
// the app is in the foreground. When this is added, you will continue to receive
// `onAuthStateChange` events with the `TOKEN_REFRESHED` or `SIGNED_OUT` event
// if the user's session is terminated. This should only be registered once.
// AppState.addEventListener('change', state => {
//   if (state === 'active') {
//     supabase.auth.startAutoRefresh()
//   } else {
//     supabase.auth.stopAutoRefresh()
//   }
// })

type AuthContextValue = {
  isAuthLoading: boolean
  isAuthenticated: boolean
  session: Session | null
  user: User | null
  signInWithEmailAndPassword: (email: string, password: string) => Promise<{ data: { user: User | null; session: Session | null } | null; error: any }>
  signOut: () => Promise<{ error: any }>
}

const SupabaseAuthContext = createContext<AuthContextValue | null>(null)

export default function SupabaseAuthProvider({ children }: { children: React.ReactNode }) {
  const [isAuthLoading, setIsAuthLoading] = useState(false)
  const [session, setSession] = useState<null | Session>(null)
  const [user, setUser] = useState<null | User>(null)
  const isAuthenticated = !!(session && user)

  // 1) Initial load + auth change subscription
  useEffect(() => {
    let mounted = true

    ;(async () => {
      const { data, error } = await supabase.auth.getSession()
      if (!mounted) return
      if (!error) {
        setSession(data.session ?? null)
        setUser(data.session?.user ?? null)
      }
      setIsAuthLoading(false)
    })()

    const { data: sub } = supabase.auth.onAuthStateChange((_event, newSession) => {
      setSession(newSession)
      setUser(newSession?.user ?? null)
    })

    return () => {
      mounted = false
      sub?.subscription?.unsubscribe?.()
    }
  }, [])

  // 2) Auto refresh while app is active (with cleanup)
  useEffect(() => {
    const handleAppState = (state: AppStateStatus) => {
      if (state === 'active') {
        supabase.auth.startAutoRefresh()
      } else {
        supabase.auth.stopAutoRefresh()
      }
    }

    const sub = AppState.addEventListener('change', handleAppState)
    // start immediately if already active
    handleAppState(AppState.currentState)

    return () => {
      supabase.auth.stopAutoRefresh()
      sub.remove()
    }
  }, [])

  async function signInWithEmailAndPassword(email: string, password: string) {
    // setIsAuthLoading(true)

    const { data, error } = await supabase.auth.signInWithPassword({
      email,
      password,
    })

    if (data || !error) {
      setSession(data.session)
      setUser(data.user)
    }
    // setIsAuthLoading(false)

    return { data, error }
  }

  async function signOut() {
    // setIsAuthLoading(true)

    const { error } = await supabase.auth.signOut()

    if (!error) {
      setSession(null)
      setUser(null)
    }

    return { error }
  }

  const value = useMemo<AuthContextValue>(
    () => ({
      isAuthLoading,
      isAuthenticated,
      session,
      user,
      signInWithEmailAndPassword,
      signOut,
    }),
    [isAuthLoading, isAuthenticated, session, user]
  )

  return <SupabaseAuthContext.Provider value={value}>{children}</SupabaseAuthContext.Provider>
}

export const useSupabaseAuth = () => {
  const context = useContext(SupabaseAuthContext)

  if (!context) throw new Error('useSupabaseAuth must be used within SupabaseAuthProvider')

  return context
}
