import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react'
import { api } from '../api/client'
import { storage } from '../lib/storage'
import type { ListThreadsAccountsData, ThreadsAccountData } from '../types/api'
import { useAuth } from '../auth/AuthContext'

type ThreadsAccountContextValue = {
  accounts: ThreadsAccountData[]
  activeAccountId: string | null
  activeAccount: ThreadsAccountData | null
  loading: boolean
  refresh: () => Promise<void>
  switchAccount: (id: string) => Promise<void>
  createAccount: (input: { displayName?: string }) => Promise<ThreadsAccountData>
  updateDisplayName: (id: string, displayName: string) => Promise<ThreadsAccountData>
}

const ThreadsAccountContext = createContext<ThreadsAccountContextValue | null>(null)

export function ThreadsAccountProvider({ children }: { children: ReactNode }) {
  const { isAuthenticated } = useAuth()
  const [accounts, setAccounts] = useState<ThreadsAccountData[]>([])
  const [activeAccountId, setActiveAccountId] = useState<string | null>(
    () => storage.getActiveThreadsAccountId() || null,
  )
  const [loading, setLoading] = useState(false)

  const refresh = useCallback(async () => {
    if (!isAuthenticated) {
      setAccounts([])
      setActiveAccountId(null)
      return
    }
    setLoading(true)
    try {
      const data = await api.get<ListThreadsAccountsData>('/api/v1/threads-accounts', { auth: true })
      setAccounts(data.list ?? [])
      const nextActive = data.active_account_id || data.list?.[0]?.id || null
      setActiveAccountId(nextActive)
      if (nextActive) storage.setActiveThreadsAccountId(nextActive)
    } finally {
      setLoading(false)
    }
  }, [isAuthenticated])

  useEffect(() => {
    if (!isAuthenticated) {
      setAccounts([])
      setActiveAccountId(null)
      return
    }
    refresh().catch(() => {
      setAccounts([])
    })
  }, [isAuthenticated, refresh])

  const switchAccount = useCallback(async (id: string) => {
    await api.post('/api/v1/threads-accounts/' + encodeURIComponent(id) + '/activate', {}, { auth: true })
    setActiveAccountId(id)
    storage.setActiveThreadsAccountId(id)
    await refresh()
  }, [refresh])

  const createAccount = useCallback(
    async (input: { displayName?: string }) => {
      const created = await api.post<ThreadsAccountData>(
        '/api/v1/threads-accounts',
        {
          display_name: input.displayName?.trim() || undefined,
          activate: true,
        },
        { auth: true },
      )
      await refresh()
      return created
    },
    [refresh],
  )

  const updateDisplayName = useCallback(
    async (id: string, displayName: string) => {
      const updated = await api.patch<ThreadsAccountData>(
        `/api/v1/threads-accounts/${encodeURIComponent(id)}`,
        { display_name: displayName.trim() },
        { auth: true },
      )
      await refresh()
      return updated
    },
    [refresh],
  )

  const activeAccount = useMemo(
    () => accounts.find((item) => item.id === activeAccountId) ?? null,
    [accounts, activeAccountId],
  )

  const value = useMemo(
    () => ({
      accounts,
      activeAccountId,
      activeAccount,
      loading,
      refresh,
      switchAccount,
      createAccount,
      updateDisplayName,
    }),
    [accounts, activeAccountId, activeAccount, loading, refresh, switchAccount, createAccount, updateDisplayName],
  )

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

export function useThreadsAccount() {
  const ctx = useContext(ThreadsAccountContext)
  if (!ctx) throw new Error('useThreadsAccount must be used within ThreadsAccountProvider')
  return ctx
}