'use client'

import { FormEvent, useEffect, useState } from 'react'
import {
    useDjangoFormCore,
    type DjangoFormState,
    type FormOptions,
    type FormErrors,
} from 'mizan'
import { useAuthContext } from '../contexts/AuthContext'
import { useStyles } from '../contexts/StylesContext'
import { getAuthDetails, AuthDetails } from '../api'

interface FooterLink {
    label: string
    href?: string
    onClick?: () => void
}

interface AuthDjangoFormProps {
    /** Form name (e.g., "login", "signup", "change_password") */
    formName: string
    /** Callback after successful form submission */
    onSuccess?: (result: any, authDetails: AuthDetails) => void
    /** Callback after failed form submission */
    onError?: (errors: any) => void
    /** Links to show in footer (e.g., "Forgot password?") */
    footerLinks?: FooterLink[]
    /** Content to render before form fields */
    preFields?: React.ReactNode
    /** Content to render after form fields (before submit button) */
    postFields?: React.ReactNode
    /** Override the submit button label from schema */
    submitLabel?: string
    /** Override the title from schema */
    title?: string
    /** Override the subtitle from schema */
    subtitle?: string
    /** Options for form behavior (validation, schema refetch, etc.) */
    formOptions?: FormOptions
}

/**
 * AuthDjangoForm renders a form from the mizan server functions
 * with styling consistent with the auth UI.
 *
 * It fetches the form schema (including title, subtitle, fields, submit label)
 * from the backend and renders it dynamically with real-time validation.
 */
export function AuthDjangoForm({
    formName,
    onSuccess,
    onError,
    footerLinks,
    preFields,
    postFields,
    submitLabel,
    title,
    subtitle,
    formOptions,
}: AuthDjangoFormProps) {
    const form = useDjangoFormCore<Record<string, unknown>>({
        name: formName,
        options: formOptions,
    })
    const { refresh } = useAuthContext()
    const styles = useStyles()
    const [mounted, setMounted] = useState(false)

    // Hydration safety: only render inputs after mount
    useEffect(() => {
        setMounted(true)
    }, [])

    const handleSubmit = async (e: FormEvent) => {
        e.preventDefault()
        const result = await form.submit()

        if (result.success) {
            // Refresh auth state and get the updated auth for callbacks
            const newAuth = await refresh()
            onSuccess?.(result.data, getAuthDetails(newAuth))
        } else {
            onError?.(result.errors)
        }
    }

    // Loading state
    if (form.loading) {
        return (
            <div className={styles.container}>
                <div className={styles.card}>
                    <div className={styles.loading}>
                        <div className={styles.spinner} />
                    </div>
                </div>
            </div>
        )
    }

    // Get form-level errors (non-field errors like "Invalid credentials")
    // These only appear after submission due to 'field-only' default
    const formErrors = form.getFormErrors()

    // Use prop overrides or schema values
    const displayTitle = title ?? form.schema?.title
    const displaySubtitle = subtitle ?? form.schema?.subtitle
    const displaySubmitLabel = submitLabel ?? form.schema?.submit_label ?? 'Submit'

    return (
        <div className={styles.container}>
            <div className={styles.card}>
                {displayTitle && (
                    <h1 className={styles.title}>{displayTitle}</h1>
                )}
                {displaySubtitle && (
                    <p className={styles.subtitle}>{displaySubtitle}</p>
                )}

                {/* Form-level errors (shown after submission) */}
                {formErrors.length > 0 && (
                    <div className={styles.error}>
                        {formErrors.map((err, i) => (
                            <p key={i}>{err.message}</p>
                        ))}
                    </div>
                )}

                <form onSubmit={handleSubmit} className={styles.form}>
                    {preFields}

                    <div className={styles.fieldsContainer}>
                        {form.schema?.fieldOrder.map(fieldName => {
                            const field = form.schema!.fields[fieldName]
                            return (
                                <AuthField
                                    key={fieldName}
                                    field={{
                                        name: fieldName,
                                        label: field.label,
                                        type: field.type,
                                        widget: field.widget,
                                        required: field.required,
                                        disabled: field.disabled,
                                        help_text: field.help_text,
                                        max_length: field.max_length,
                                        choices: field.choices,
                                    }}
                                    value={form.data[fieldName]}
                                    mounted={mounted}
                                    touched={form.touchedFields.has(fieldName)}
                                    errors={form.getFieldErrors(fieldName)}
                                    onChange={(value) => form.set(fieldName, value)}
                                    onBlur={() => form.touch(fieldName)}
                                />
                            )
                        })}
                    </div>

                    {postFields}

                    <button
                        type="submit"
                        disabled={form.submitting || form.validating}
                        className={styles.submit}
                    >
                        {form.submitting ? 'Submitting...' : displaySubmitLabel}
                    </button>
                </form>

                {footerLinks && footerLinks.length > 0 && (
                    <div className={styles.footer}>
                        {footerLinks.map((link, i) => (
                            link.onClick ? (
                                <button key={i} type="button" onClick={link.onClick} className={styles.link}>
                                    {link.label}
                                </button>
                            ) : link.href ? (
                                <a key={i} href={link.href} className={styles.link}>
                                    {link.label}
                                </a>
                            ) : null
                        ))}
                    </div>
                )}
            </div>
        </div>
    )
}

/**
 * Internal field component with hydration-safe rendering
 */
interface AuthFieldProps {
    field: {
        name: string
        label: string
        type: string
        widget: string
        required: boolean
        disabled: boolean
        help_text: string
        max_length?: number | null
        choices?: Array<{ value: string; label: string }> | null
    }
    value: any
    mounted: boolean
    touched: boolean
    errors: Array<{ message: string }>
    onChange: (value: any) => void
    onBlur: () => void
}

function AuthField({ field, value, mounted, touched, errors, onChange, onBlur }: AuthFieldProps) {
    const styles = useStyles()

    const renderInput = () => {
        // Select dropdown
        if (field.choices && (field.widget === 'Select' || field.type === 'select')) {
            return (
                <select
                    value={value || ''}
                    onChange={(e) => onChange(e.target.value)}
                    onBlur={onBlur}
                    required={field.required}
                    disabled={field.disabled}
                    className={styles.fieldInput}
                >
                    {field.choices.map((choice) => (
                        <option key={choice.value} value={choice.value}>
                            {choice.label}
                        </option>
                    ))}
                </select>
            )
        }

        // Radio buttons
        if (field.choices && field.widget === 'RadioSelect') {
            return (
                <div className={styles.radioGroup}>
                    {field.choices.map((choice) => (
                        <label key={choice.value} className={styles.radioItem}>
                            <input
                                type="radio"
                                name={field.name}
                                value={choice.value}
                                checked={value === choice.value}
                                onChange={(e) => onChange(e.target.value)}
                                onBlur={onBlur}
                                required={field.required}
                                disabled={field.disabled}
                            />
                            <span>{choice.label}</span>
                        </label>
                    ))}
                </div>
            )
        }

        // Checkbox
        if (field.type === 'checkbox') {
            return (
                <input
                    type="checkbox"
                    checked={!!value}
                    onChange={(e) => onChange(e.target.checked)}
                    onBlur={onBlur}
                    required={field.required}
                    disabled={field.disabled}
                    className={styles.checkbox}
                />
            )
        }

        // Textarea
        if (field.widget === 'Textarea') {
            return (
                <textarea
                    value={value || ''}
                    onChange={(e) => onChange(e.target.value)}
                    onBlur={onBlur}
                    required={field.required}
                    disabled={field.disabled}
                    maxLength={field.max_length || undefined}
                    className={styles.fieldInput}
                />
            )
        }

        // Default: text input (text, password, email, etc.)
        return (
            <input
                type={field.type}
                value={value || ''}
                onChange={(e) => onChange(e.target.value)}
                onBlur={onBlur}
                required={field.required}
                disabled={field.disabled}
                maxLength={field.max_length || undefined}
                className={styles.fieldInput}
                autoComplete="off"
            />
        )
    }

    return (
        <div className={styles.field}>
            <label className={styles.fieldLabel}>
                {field.label}
            </label>

            {/* Hydration-safe: render placeholder until mounted */}
            {mounted ? (
                renderInput()
            ) : (
                <div className={styles.fieldInput} style={{ minHeight: '2.75rem' }} />
            )}

            {/* Field errors (only show if touched) */}
            {touched && errors.map((err, i) => (
                <p key={i} className={styles.fieldError}>{err.message}</p>
            ))}
        </div>
    )
}
