'use client'

import { useMemo } from 'react'
import { useDjangoCSRClient, Auth } from 'mizan/client/react'
import { useAuthContext } from './AuthContext'
import { createAPI, AllauthAPI, BrowserFormAction } from '../api'

/**
 * Browser form action for OAuth redirects.
 * Creates and submits a form programmatically.
 */
const browserFormAction: BrowserFormAction = (action: string, data: Record<string, string>) => {
    const form = document.createElement('form')
    form.method = 'POST'
    form.action = action

    for (const [key, value] of Object.entries(data)) {
        const input = document.createElement('input')
        input.type = 'hidden'
        input.name = key
        input.value = value
        form.appendChild(input)
    }

    document.body.appendChild(form)
    form.submit()
}

/**
 * Hook that returns the Allauth API with automatic auth refresh on relevant responses.
 *
 * Automatically triggers auth refresh when:
 * - 401 with flows (authentication required)
 * - 410 (session gone)
 * - 200 with is_authenticated (successful auth)
 */
export function useAllauthAPI(): AllauthAPI {
    const client = useDjangoCSRClient(Auth.SESSION)
    const { refresh } = useAuthContext()

    return useMemo(() => {
        const authRequest = async (method: string, path: string, data?: any, headers?: Record<string, string>) => {
            const resp = await client.request(method, `/_allauth/browser/v1${path}`, data, headers)

            if (resp.status >= 500) {
                throw new Error(`Allauth request failed: ${resp.status} ${resp.statusText}`)
            }

            try {
                return await resp.json()
            } catch {
                throw new Error(`Allauth request failed: ${resp.status} ${resp.statusText}`)
            }
        }

        return createAPI(
            async (method, path, data?, headers?) => {
                const resp = await authRequest(method, path, { ...(data as object), client: 'browser' }, headers)

                // Auto-refresh auth state on relevant responses
                if (resp.status === 401 && resp.data?.flows) {
                    refresh(resp)
                } else if ([401, 410].includes(resp.status) || (resp.status === 200 && resp.meta?.is_authenticated)) {
                    refresh()
                }

                return resp
            },
            browserFormAction
        )
    }, [client, refresh])
}
