import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react'
import { useLocation } from 'react-router-dom'
import { api } from '../api/client'
import {
  buildOnboardingSnapshot,
  connectionIsReady,
  type OnboardingSnapshot,
} from '../lib/onboarding'
import { useThreadsAccount } from '../threads/ThreadsAccountContext'
import type { ListPersonasData, ThreadsAccountConnectionData } from '../types/api'

type OnboardingContextValue = OnboardingSnapshot & {
  refresh: () => Promise<OnboardingSnapshot>
}

const OnboardingContext = createContext<OnboardingContextValue | null>(null)

export function OnboardingProvider({ children }: { children: ReactNode }) {
  const { pathname } = useLocation()
  const { accounts, activeAccountId, loading: accountsLoading } = useThreadsAccount()
  const [personasLoading, setPersonasLoading] = useState(true)
  const [personaCount, setPersonaCount] = useState(0)
  const [connectionLoading, setConnectionLoading] = useState(false)
  const [connectionReady, setConnectionReady] = useState(false)

  const refresh = useCallback(async () => {
    setPersonasLoading(true)
    let nextPersonaCount = 0
    try {
      const personas = await api.get<ListPersonasData>('/api/v1/personas', { auth: true })
      nextPersonaCount = personas.list?.length ?? 0
      setPersonaCount(nextPersonaCount)
    } catch {
      setPersonaCount(0)
    } finally {
      setPersonasLoading(false)
    }

    if (!activeAccountId) {
      setConnectionReady(false)
      setConnectionLoading(false)
      return buildOnboardingSnapshot({
        accountsLoading,
        personasLoading: false,
        connectionLoading: false,
        accountCount: accounts.length,
        personaCount: nextPersonaCount,
        connectionReady: false,
      })
    }

    setConnectionLoading(true)
    let nextConnectionReady = false
    try {
      const connection = await api.get<ThreadsAccountConnectionData>(
        `/api/v1/threads-accounts/${encodeURIComponent(activeAccountId)}/connection`,
        { auth: true },
      )
      nextConnectionReady = connectionIsReady(connection)
      setConnectionReady(nextConnectionReady)
    } catch {
      setConnectionReady(false)
    } finally {
      setConnectionLoading(false)
    }

    return buildOnboardingSnapshot({
      accountsLoading: false,
      personasLoading: false,
      connectionLoading: false,
      accountCount: accounts.length,
      personaCount: nextPersonaCount,
      connectionReady: nextConnectionReady,
    })
  }, [accounts.length, accountsLoading, activeAccountId])

  useEffect(() => {
    refresh().catch(() => undefined)
  }, [accounts, activeAccountId, pathname, refresh])

  const snapshot = useMemo(
    () =>
      buildOnboardingSnapshot({
        accountsLoading,
        personasLoading,
        connectionLoading,
        accountCount: accounts.length,
        personaCount,
        connectionReady,
      }),
    [
      accounts.length,
      accountsLoading,
      connectionLoading,
      connectionReady,
      personaCount,
      personasLoading,
    ],
  )

  const value = useMemo(
    () => ({
      ...snapshot,
      refresh,
    }),
    [snapshot, refresh],
  )

  return <OnboardingContext.Provider value={value}>{children}</OnboardingContext.Provider>
}

export function useOnboarding() {
  const ctx = useContext(OnboardingContext)
  if (!ctx) throw new Error('useOnboarding must be used within OnboardingProvider')
  return ctx
}