import { Head, Link, router } from '@inertiajs/react';
import { useEffect, useState } from 'react';

import HeadingSmall from '@/components/heading-small';
import { SortableHeader } from '@/components/sortable-header';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { useUserTimezone } from '@/hooks/use-user-timezone';
import AppLayout from '@/layouts/app-layout';
import { formatDateTime } from '@/lib/format-date';
import { productProperName } from '@/lib/utils';
import { archive, build, bulkArchive, confirmationPdf, index, index as enrollmentRequestsIndex, pushToGoogleSheet, rebuild, resendConfirmation } from '@/actions/App/Http/Controllers/Admin/EnrollmentRequestController';
import { index as creditCheckRequestsIndex } from '@/actions/App/Http/Controllers/Admin/CreditCheckRequestController';
import { build as buildFraudCheck, index as supplierFraudChecksIndex } from '@/actions/App/Http/Controllers/Admin/SupplierFraudCheckController';
import { index as apiLogsIndex } from '@/actions/App/Http/Controllers/Admin/PublicApiRequestLogController';
import { show as webFormSessionsShow } from '@/routes/admin/web-form-sessions';

type SupplierProduct = {
    id: number;
    supplier: { id: number, name: string } | null;
};

type Utility = {
    id: number;
    name: string;
};

type Product = {
    id: number;
    name: string;
    supplier_product: SupplierProduct | null;
    utility: Utility | null;
}

type ApiLog = {
    id: number;
    method: string;
    path: string;
    response_status: number | null;
    created_at: string;
};

type IntegrationLog = {
    id: number;
    integration: { id: number; key: string; name: string } | null;
    status: string;
    context: Record<string, unknown> | null;
    error_message: string | null;
    created_at: string;
};

type EnrollmentRequest = {
    id: number;
    product: Product;
    status: string | null;
    body: Record<string, unknown> | null;
    utm: Record<string, unknown> | null;
    ip_address: string | null;
    credit_check_authorization_token: string | null;
    fraud_check_authorization_token: string | null;
    created_at: string;
    processed_at: string | null;
    deleted_at: string | null;
    confirmations_count: number;
    credit_check_requests_count: number;
    supplier_fraud_checks_count: number;
    requires_fraud_check: boolean;
    requires_credit_check: boolean;
    customer_email: string | null;
    has_filtered_email_domain: boolean;
    api_log: ApiLog | null;
    integration_logs: IntegrationLog[];
    web_form_session: { id: number; session_id: string } | null;
    confirmation: {
        id: number;
        email: string;
        pdf_path: string | null;
        sent_at: string | null;
        created_at: string;
    } | null;
    confirmations: {
        id: number;
        email: string;
        pdf_path: string | null;
        sent_at: string | null;
        created_at: string;
    }[];
};

type PaginatedEnrollmentRequests = {
    data: EnrollmentRequest[];
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
    next_page_url: string | null;
    prev_page_url: string | null;
    links: { url: string | null; label: string; active: boolean }[];
}


type Filters = {
    search: string;
    status: string;
    supplier_id: string;
    utility_id: string;
    sort_by: string;
    sort_direction: string;
    trashed: string;
};

type Props = {
    enrollmentRequests: PaginatedEnrollmentRequests;
    filters: Filters;
    suppliers: { id: number; name: string }[];
    utilities: { id: number; name: string }[];
};


function StatusBadge({ status }: { status: string | null }) {
    if (!status) return <span className="text-zinc-400">—</span>;

    const colors: Record<string, string> = {
        pending: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
        processed: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
        inactive: 'bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400',
        archived: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
    };

    return (
        <span
            className={`inline-block rounded-full px-2 py-0.5 text-xs font-medium ${colors[status] ?? 'bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400'}`}
        >
            {status}
        </span>
    );
}

function EmailCell({ email, isFiltered }: { email: string | null; isFiltered: boolean }) {
    if (!email) return <span className="text-zinc-400">—</span>;

    return (
        <span
            className={isFiltered ? 'text-red-600 dark:text-red-400' : ''}
            title={isFiltered ? 'Filtered domain — never auto-submitted to supplier' : undefined}
        >
            {email}
        </span>
    );
}

function BodyFields({ body }: { body: Record<string, unknown> | null }) {
    if (!body || Object.keys(body).length === 0) {
        return <span className="text-zinc-400 text-sm">No data</span>;
    }

    return (
        <dl className="divide-y divide-zinc-100 dark:divide-zinc-800">
            {Object.entries(body).map(([key, value]) => (
                <div key={key} className="grid grid-cols-[180px_1fr] gap-2 py-2 text-sm">
                    <dt className="font-medium text-zinc-500 dark:text-zinc-400 truncate">{key}</dt>
                    <dd className="text-zinc-900 dark:text-zinc-100 break-all">
                        {value === null || value === undefined
                            ? <span className="text-zinc-400">—</span>
                            : typeof value === 'object'
                                ? <pre className="whitespace-pre-wrap font-mono text-xs">{JSON.stringify(value, null, 2)}</pre>
                                : String(value)}
                    </dd>
                </div>
            ))}
        </dl>
    );
}

function EnrollmentRequestDetailModal({
    enrollmentRequest,
    open,
    onOpenChange,
}: {
    enrollmentRequest: EnrollmentRequest | null;
    open: boolean;
    onOpenChange: (open: boolean) => void;
}) {
    const timezone = useUserTimezone();
    const [showRawJson, setShowRawJson] = useState(false);

    if (!enrollmentRequest) return null;

    const { product, status, ip_address, credit_check_authorization_token, fraud_check_authorization_token, created_at, body, utm, confirmation, confirmations, credit_check_requests_count, supplier_fraud_checks_count, api_log, integration_logs, customer_email, has_filtered_email_domain, web_form_session } = enrollmentRequest;
    const googleSheetLogs = integration_logs.filter((log) => log.integration?.key === 'google_sheets');
    const supplier = product.supplier_product?.supplier?.name ?? '—';
    const utility = product.utility?.name ?? '—';

    return (
        <Dialog open={open} onOpenChange={(v) => { if (!v) setShowRawJson(false); onOpenChange(v); }}>
            <DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
                <DialogHeader>
                    <DialogTitle>Enrollment Request #{enrollmentRequest.id}</DialogTitle>
                </DialogHeader>

                <div className="space-y-6 pt-2">
                    {/* Meta */}
                    <dl className="divide-y divide-zinc-100 dark:divide-zinc-800">
                        {[
                            ['Product', productProperName(product.name)],
                            ['Utility', utility],
                            ['Supplier', supplier],
                            ['Email', <EmailCell email={customer_email} isFiltered={has_filtered_email_domain} />],
                            ['Status', <StatusBadge status={status} />],
                            ['IP Address', ip_address ?? '—'],
                            ...(credit_check_authorization_token
                                ? [['Credit Check Auth Token', <span className="font-mono text-xs break-all">{credit_check_authorization_token}</span>]]
                                : []),
                            ...(fraud_check_authorization_token
                                ? [['Fraud Check Auth Token', <span className="font-mono text-xs break-all">{fraud_check_authorization_token}</span>]]
                                : []),
                            ['Submitted', formatDateTime(created_at, timezone)],
                            ['Credit Check Requests', credit_check_requests_count > 0
                                ? (
                                    <a
                                        href={creditCheckRequestsIndex.url({ query: { enrollment_request_id: String(enrollmentRequest.id) } })}
                                        className="inline-flex items-center gap-1 text-blue-600 hover:text-blue-800 hover:underline dark:text-blue-400 dark:hover:text-blue-300"
                                    >
                                        {credit_check_requests_count} {credit_check_requests_count === 1 ? 'request' : 'requests'} →
                                    </a>
                                )
                                : <span className="text-zinc-400">None</span>
                            ],
                            ['API Log', api_log
                                ? (
                                    <a
                                        href={apiLogsIndex.url({ query: { id: String(api_log.id) } })}
                                        className="inline-flex items-center gap-1 font-mono text-xs text-blue-600 hover:text-blue-800 hover:underline dark:text-blue-400 dark:hover:text-blue-300"
                                    >
                                        #{api_log.id} · {api_log.method} · {api_log.response_status} →
                                    </a>
                                )
                                : <span className="text-zinc-400">None</span>
                            ],
                            ['Web Form Session', web_form_session
                                ? (
                                    <Link
                                        href={webFormSessionsShow.url(web_form_session.id)}
                                        className="inline-flex items-center gap-1 font-mono text-xs text-blue-600 hover:text-blue-800 hover:underline dark:text-blue-400 dark:hover:text-blue-300"
                                    >
                                        {web_form_session.session_id} →
                                    </Link>
                                )
                                : <span className="text-zinc-400">None</span>
                            ],
                            ['Fraud Checks', supplier_fraud_checks_count > 0
                                ? (
                                    <a
                                        href={supplierFraudChecksIndex.url({ query: { enrollment_request_id: String(enrollmentRequest.id) } })}
                                        className="inline-flex items-center gap-1 text-blue-600 hover:text-blue-800 hover:underline dark:text-blue-400 dark:hover:text-blue-300"
                                    >
                                        {supplier_fraud_checks_count} {supplier_fraud_checks_count === 1 ? 'fraud check' : 'fraud checks'} →
                                    </a>
                                )
                                : <span className="text-zinc-400">None</span>
                            ],
                        ].map(([label, value]) => (
                            <div key={String(label)} className="grid grid-cols-[180px_1fr] gap-2 py-2 text-sm">
                                <dt className="font-medium text-zinc-500 dark:text-zinc-400">{label}</dt>
                                <dd className="text-zinc-900 dark:text-zinc-100">{value}</dd>
                            </div>
                        ))}
                    </dl>

                    {/* Confirmation */}
                    {confirmation && (
                        <div>
                            <h3 className="mb-2 text-sm font-semibold text-zinc-700 dark:text-zinc-300">Confirmation History</h3>
                            <div className="overflow-hidden rounded-md border border-zinc-200 dark:border-zinc-800">
                                <div className="overflow-x-auto">
                                    <table className="w-full text-left text-sm">
                                        <thead className="border-b border-zinc-200 bg-zinc-50 text-xs uppercase text-zinc-600 dark:border-zinc-800 dark:bg-zinc-900/60 dark:text-zinc-400">
                                            <tr>
                                                <th className="px-3 py-2">Sent</th>
                                                <th className="px-3 py-2">Email</th>
                                                <th className="px-3 py-2">Status</th>
                                                <th className="px-3 py-2 text-right">PDF</th>
                                            </tr>
                                        </thead>
                                        <tbody className="divide-y divide-zinc-100 dark:divide-zinc-800">
                                            {confirmations.map((notification) => (
                                                <tr key={notification.id}>
                                                    <td className="px-3 py-2 text-zinc-700 dark:text-zinc-300">{formatDateTime(notification.created_at, timezone)}</td>
                                                    <td className={`px-3 py-2 break-all ${has_filtered_email_domain ? 'text-red-600 dark:text-red-400' : 'text-zinc-700 dark:text-zinc-300'}`}>{notification.email || '—'}</td>
                                                    <td className="px-3 py-2 text-zinc-700 dark:text-zinc-300">{notification.sent_at ? 'Sent' : 'Not sent'}</td>
                                                    <td className="px-3 py-2 text-right">
                                                        {notification.pdf_path ? (
                                                            <a
                                                                href={confirmationPdf.url([enrollmentRequest.id, notification.id])}
                                                                target="_blank"
                                                                rel="noreferrer"
                                                                className="inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700"
                                                            >
                                                                <svg className="size-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                                                    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
                                                                    <polyline points="14 2 14 8 20 8" />
                                                                </svg>
                                                                View PDF
                                                            </a>
                                                        ) : (
                                                            <span className="text-xs text-zinc-400">—</span>
                                                        )}
                                                    </td>
                                                </tr>
                                            ))}
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                    )}

                    {/* Google Sheet export history */}
                    <div>
                        <div className="mb-2 flex items-center justify-between">
                            <h3 className="text-sm font-semibold text-zinc-700 dark:text-zinc-300">Google Sheet Export History</h3>
                            <button
                                type="button"
                                onClick={() => router.post(pushToGoogleSheet.url(enrollmentRequest.id), {}, { preserveScroll: true, preserveState: true })}
                                className="rounded-md border border-zinc-200 bg-white px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800"
                            >
                                {googleSheetLogs.length > 0 ? 'Re-push to Sheet' : 'Push to Sheet'}
                            </button>
                        </div>
                        {googleSheetLogs.length > 0 ? (
                            <div className="overflow-hidden rounded-md border border-zinc-200 dark:border-zinc-800">
                                <div className="overflow-x-auto">
                                    <table className="w-full text-left text-sm">
                                        <thead className="border-b border-zinc-200 bg-zinc-50 text-xs uppercase text-zinc-600 dark:border-zinc-800 dark:bg-zinc-900/60 dark:text-zinc-400">
                                            <tr>
                                                <th className="px-3 py-2">Date</th>
                                                <th className="px-3 py-2">Status</th>
                                                <th className="px-3 py-2">Spreadsheet</th>
                                                <th className="px-3 py-2">Details</th>
                                            </tr>
                                        </thead>
                                        <tbody className="divide-y divide-zinc-100 dark:divide-zinc-800">
                                            {googleSheetLogs.map((log) => (
                                                <tr key={log.id}>
                                                    <td className="px-3 py-2 text-zinc-700 dark:text-zinc-300">{formatDateTime(log.created_at, timezone)}</td>
                                                    <td className="px-3 py-2">
                                                        <span
                                                            className={`inline-block rounded-full px-2 py-0.5 text-xs font-medium ${
                                                                log.status === 'success'
                                                                    ? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'
                                                                    : 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'
                                                            }`}
                                                        >
                                                            {log.status}
                                                        </span>
                                                    </td>
                                                    <td className="px-3 py-2 font-mono text-xs text-zinc-700 dark:text-zinc-300">
                                                        {String(log.context?.spreadsheet_id ?? '—')}
                                                    </td>
                                                    <td className="px-3 py-2 text-zinc-700 dark:text-zinc-300">
                                                        {log.error_message ?? '—'}
                                                    </td>
                                                </tr>
                                            ))}
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        ) : (
                            <p className="text-sm text-zinc-400">Not yet exported.</p>
                        )}
                    </div>

                    {/* UTM parameters */}
                    <div>
                        <h3 className="mb-2 text-sm font-semibold text-zinc-700 dark:text-zinc-300">UTM Parameters</h3>
                        <BodyFields body={utm} />
                    </div>

                    {/* Body */}
                    <div>
                        <div className="flex items-center justify-between mb-2">
                            <h3 className="text-sm font-semibold text-zinc-700 dark:text-zinc-300">Request Body</h3>
                            {body && Object.keys(body).length > 0 && (
                                <button
                                    type="button"
                                    onClick={() => setShowRawJson((v) => !v)}
                                    className="rounded-md border border-zinc-200 bg-white px-2.5 py-1 text-xs font-medium text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-800"
                                >
                                    {showRawJson ? 'Formatted' : 'Raw JSON'}
                                </button>
                            )}
                        </div>
                        {showRawJson ? (
                            <pre className="overflow-x-auto rounded-md bg-zinc-50 p-3 font-mono text-xs text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200">
                                {JSON.stringify(body, null, 2)}
                            </pre>
                        ) : (
                            <BodyFields body={body} />
                        )}
                    </div>
                </div>
            </DialogContent>
        </Dialog>
    );
}

function ArchiveConfirmDialog({
    open,
    onOpenChange,
    onConfirm,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    onConfirm: () => void;
}) {
    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="max-w-sm">
                <DialogHeader>
                    <DialogTitle>Archive enrollment request?</DialogTitle>
                </DialogHeader>
                <p className="text-sm text-zinc-600 dark:text-zinc-400">
                    This record will be soft-deleted and hidden from the default view. You can view archived records using the "Show archived" toggle.
                </p>
                <div className="flex justify-end gap-2 pt-2">
                    <button
                        type="button"
                        onClick={() => onOpenChange(false)}
                        className="rounded-md px-3 py-2 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                    >
                        Cancel
                    </button>
                    <button
                        type="button"
                        onClick={onConfirm}
                        className="rounded-md bg-red-600 px-3 py-2 text-sm font-medium text-white hover:bg-red-700 dark:bg-red-700 dark:hover:bg-red-600"
                    >
                        Archive
                    </button>
                </div>
            </DialogContent>
        </Dialog>
    );
}

function BulkArchiveConfirmDialog({
    open,
    onOpenChange,
    onConfirm,
    count,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    onConfirm: () => void;
    count: number;
}) {
    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="max-w-sm">
                <DialogHeader>
                    <DialogTitle>Archive {count} enrollment {count === 1 ? 'request' : 'requests'}?</DialogTitle>
                </DialogHeader>
                <p className="text-sm text-zinc-600 dark:text-zinc-400">
                    These records will be soft-deleted and hidden from the default view. You can view archived records using the "Show archived" toggle.
                </p>
                <div className="flex justify-end gap-2 pt-2">
                    <button
                        type="button"
                        onClick={() => onOpenChange(false)}
                        className="rounded-md px-3 py-2 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                    >
                        Cancel
                    </button>
                    <button
                        type="button"
                        onClick={onConfirm}
                        className="rounded-md bg-red-600 px-3 py-2 text-sm font-medium text-white hover:bg-red-700 dark:bg-red-700 dark:hover:bg-red-600"
                    >
                        Archive
                    </button>
                </div>
            </DialogContent>
        </Dialog>
    );
}

function RebuildConfirmDialog({
    open,
    onOpenChange,
    onConfirm,
    enrollmentRequest,
}: {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    onConfirm: () => void;
    enrollmentRequest: EnrollmentRequest | null;
}) {
    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="max-w-sm">
                <DialogHeader>
                    <DialogTitle>Rebuild supplier enrollment?</DialogTitle>
                </DialogHeader>
                <p className="text-sm text-zinc-600 dark:text-zinc-400">
                    A new supplier enrollment record will be created for enrollment request{' '}
                    {enrollmentRequest ? <strong>#{enrollmentRequest.id}</strong> : null}. Any existing supplier enrollment records for this request will remain intact.
                </p>
                <div className="flex justify-end gap-2 pt-2">
                    <button
                        type="button"
                        onClick={() => onOpenChange(false)}
                        className="rounded-md px-3 py-2 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                    >
                        Cancel
                    </button>
                    <button
                        type="button"
                        onClick={onConfirm}
                        className="rounded-md bg-zinc-900 px-3 py-2 text-sm font-medium text-white hover:bg-zinc-800 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200"
                    >
                        Rebuild
                    </button>
                </div>
            </DialogContent>
        </Dialog>
    );
}

type CreditCheckFormField = {
    name: string;
    label: string;
    type: string;
    options: { value: string; label: string }[] | null;
    required: boolean;
    placeholder: string | null;
    validation_pattern: string | null;
    validation_message: string | null;
    help_text: string | null;
    display_order: number;
    value?: string;
};

type CreditCheckWebFormSection = {
    name: string | null;
    label: string | null;
    description: string | null;
    display_order: number;
    fields: CreditCheckFormField[];
};

type CreditCheckWebFormData = {
    id: number;
    slug: string;
    name: string;
    description: string | null;
    post_path: string;
    sections: CreditCheckWebFormSection[];
};

const fieldInputClasses =
    'w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm shadow-sm dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100';

function CreditCheckModal({
    enrollmentRequest,
    open,
    onOpenChange,
}: {
    enrollmentRequest: EnrollmentRequest | null;
    open: boolean;
    onOpenChange: (open: boolean) => void;
}) {
    const [webFormData, setWebFormData] = useState<CreditCheckWebFormData | null>(null);
    const [loading, setLoading] = useState(false);
    const [formValues, setFormValues] = useState<Record<string, string>>({});
    const [submitting, setSubmitting] = useState(false);
    const [result, setResult] = useState<{ ok: boolean; body: unknown } | null>(null);

    useEffect(() => {
        if (!open || !enrollmentRequest) {
            setWebFormData(null);
            setFormValues({});
            setResult(null);
            return;
        }

        setLoading(true);
        setResult(null);

        fetch(`/api/public/v1/web-forms/credit-check?product_id=${enrollmentRequest.product.id}&enrollment_id=${enrollmentRequest.id}`)
            .then((r) => r.json() as Promise<{ data: CreditCheckWebFormData }>)
            .then((json) => {
                setWebFormData(json.data);
                const values: Record<string, string> = {};
                for (const field of json.data.sections.flatMap((s) => s.fields)) {
                    values[field.name] = field.value ?? '';
                }
                setFormValues(values);
            })
            .finally(() => setLoading(false));
    }, [open, enrollmentRequest]);

    async function handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        if (!enrollmentRequest || !webFormData) return;

        setSubmitting(true);
        setResult(null);

        const data: Record<string, unknown> = { enrollment_id: enrollmentRequest.id };
        for (const field of webFormData.sections.flatMap((s) => s.fields)) {
            const val = formValues[field.name] ?? '';
            if (val !== '') {
                data[field.name] = val;
            }
        }

        try {
            const response = await fetch('/api/public/v1/credit-check', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
                body: JSON.stringify({
                    ip_address: enrollmentRequest.ip_address ?? '127.0.0.1',
                    data,
                }),
            });

            const body = await response.json();
            const ok = response.status === 201 || response.status === 202;
            setResult({ ok, body });

            if (ok) {
                router.reload({ only: ['enrollmentRequests'] });
            }
        } catch (err) {
            setResult({ ok: false, body: { message: String(err) } });
        } finally {
            setSubmitting(false);
        }
    }

    function renderField(field: CreditCheckFormField) {
        const value = formValues[field.name] ?? '';
        const onChange = (val: string) => setFormValues((prev) => ({ ...prev, [field.name]: val }));

        return (
            <div key={field.name} className="grid grid-cols-[220px_1fr] gap-3 items-start py-2 border-t border-zinc-100 dark:border-zinc-800 first:border-0">
                <label htmlFor={field.name} className="text-sm font-medium text-zinc-700 dark:text-zinc-300 pt-2 leading-tight">
                    {field.label}
                    {field.required && <span className="ml-0.5 text-red-500">*</span>}
                </label>
                <div className="space-y-1">
                    {field.type === 'select' && field.options ? (
                        <select id={field.name} value={value} onChange={(e) => onChange(e.target.value)} className={fieldInputClasses}>
                            <option value="">— select —</option>
                            {field.options.map((opt) => (
                                <option key={opt.value} value={opt.value}>
                                    {opt.label}
                                </option>
                            ))}
                        </select>
                    ) : field.type === 'checkbox' ? (
                        <input
                            type="checkbox"
                            id={field.name}
                            checked={value === 'true'}
                            onChange={(e) => onChange(e.target.checked ? 'true' : 'false')}
                            className="size-4 rounded border-zinc-300 dark:border-zinc-700"
                        />
                    ) : (
                        <input
                            id={field.name}
                            type={field.type === 'email' ? 'email' : field.type === 'date' ? 'date' : 'text'}
                            value={value}
                            onChange={(e) => onChange(e.target.value)}
                            placeholder={field.placeholder ?? ''}
                            className={fieldInputClasses}
                        />
                    )}
                    {field.help_text && <p className="text-xs text-zinc-500 dark:text-zinc-400">{field.help_text}</p>}
                </div>
            </div>
        );
    }

    if (!enrollmentRequest) return null;

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
                <DialogHeader>
                    <DialogTitle>Credit Check — Enrollment Request #{enrollmentRequest.id}</DialogTitle>
                </DialogHeader>

                {loading && <p className="text-sm text-zinc-500 dark:text-zinc-400">Loading form…</p>}

                {webFormData && !loading && (
                    <form onSubmit={handleSubmit} className="space-y-4">
                        <div className="space-y-4">
                            {webFormData.sections.map((section) => (
                                <div key={section.name ?? 'unsectioned'}>
                                    {section.label && (
                                        <h3 className="mb-1 text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:text-zinc-400">
                                            {section.label}
                                        </h3>
                                    )}
                                    {section.description && (
                                        <p className="mb-2 text-xs text-zinc-500 dark:text-zinc-400">
                                            {section.description}
                                        </p>
                                    )}
                                    <div>{section.fields.map((field) => renderField(field))}</div>
                                </div>
                            ))}
                        </div>
                        <div className="flex justify-end gap-2 pt-2">
                            <button
                                type="button"
                                onClick={() => onOpenChange(false)}
                                className="rounded-md px-3 py-2 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                            >
                                Cancel
                            </button>
                            <button
                                type="submit"
                                disabled={submitting}
                                className="rounded-md bg-zinc-900 px-3 py-2 text-sm font-medium text-white hover:bg-zinc-800 disabled:opacity-50 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200"
                            >
                                {submitting ? 'Submitting…' : 'Run Credit Check'}
                            </button>
                        </div>
                    </form>
                )}

                {result && (
                    <div
                        className={`rounded-md border p-4 ${
                            result.ok
                                ? 'border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-950/30'
                                : 'border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950/30'
                        }`}
                    >
                        <h3
                            className={`mb-2 text-sm font-semibold ${
                                result.ok ? 'text-green-800 dark:text-green-300' : 'text-red-800 dark:text-red-300'
                            }`}
                        >
                            {result.ok ? 'Credit Check Submitted' : 'Submission Failed'}
                        </h3>
                        <pre className="overflow-x-auto text-xs font-mono leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap">
                            {JSON.stringify(result.body, null, 2)}
                        </pre>
                    </div>
                )}
            </DialogContent>
        </Dialog>
    );
}

const breadcrumbs = [{ title: 'Enrollment Requests', href: index.url() }];

const selectClasses =
    'rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm shadow-sm dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100';


export default function EnrollmentRequests({ enrollmentRequests, filters, suppliers, utilities } : Props) {
    const timezone = useUserTimezone();

    const [search, setSearch] = useState(filters.search);
    const [selectedRequest, setSelectedRequest] = useState<EnrollmentRequest | null>(null);
    const [archiveTarget, setArchiveTarget] = useState<EnrollmentRequest | null>(null);
    const [rebuildTarget, setRebuildTarget] = useState<EnrollmentRequest | null>(null);
    const [creditCheckTarget, setCreditCheckTarget] = useState<EnrollmentRequest | null>(null);
    const [selectedIds, setSelectedIds] = useState<number[]>([]);
    const [bulkArchiveOpen, setBulkArchiveOpen] = useState(false);

    const sortColumn = filters.sort_by || 'created_at';
    const sortDirection = (filters.sort_direction || 'desc') as 'asc' | 'desc';
    const showTrashed = filters.trashed === '1';

    function toggleSort(column: string) {
        if (column === sortColumn) {
            applyFilters({ sort_by: column, sort_direction: sortDirection === 'asc' ? 'desc' : 'asc' });
        } else {
            applyFilters({ sort_by: column, sort_direction: 'asc' });
        }
    }

    function applyFilters(overrides: Partial<Filters> = {}) {
        const merged = { ...filters, ...overrides };

        router.get(
            enrollmentRequestsIndex.url(),
            Object.fromEntries(Object.entries(merged).filter(([, v]) => v !== '')),
            { preserveState: true, replace: true },
        );
    }

    function confirmArchive() {
        if (!archiveTarget) return;
        router.delete(archive.url(archiveTarget.id), {
            preserveScroll: true,
            onFinish: () => setArchiveTarget(null),
        });
    }

    function confirmRebuild() {
        if (!rebuildTarget) return;
        router.post(rebuild.url(rebuildTarget.id), {}, {
            preserveScroll: true,
            onFinish: () => setRebuildTarget(null),
        });
    }

    const archivableIds = enrollmentRequests.data.filter((e) => !e.deleted_at).map((e) => e.id);
    const allSelected = archivableIds.length > 0 && archivableIds.every((id) => selectedIds.includes(id));

    function toggleSelectAll() {
        setSelectedIds(allSelected ? [] : archivableIds);
    }

    function toggleSelected(id: number) {
        setSelectedIds((prev) => (prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id]));
    }

    function confirmBulkArchive() {
        router.delete(bulkArchive.url(), {
            data: { ids: selectedIds },
            preserveScroll: true,
            onFinish: () => {
                setBulkArchiveOpen(false);
                setSelectedIds([]);
            },
        });
    }

    const hasActiveFilters =
        filters.search ||
        filters.status ||
        filters.supplier_id ||
        filters.utility_id ||
        filters.trashed;

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title="Enrollment Requests" />

            <h1 className="sr-only">Enrollment Requests</h1>

            <div className="space-y-6">
                <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
                    <HeadingSmall
                        title="Enrollment Requests"
                        description="Manage customer enrollment requests"
                    />

                    {/* Filters */}
                    <div className="flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-end">
                        <div className="flex flex-col gap-1 sm:min-w-60">
                            <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                Search
                            </label>
                            <input
                                type="text"
                                value={search}
                                onChange={(e) => setSearch(e.target.value)}
                                onKeyDown={(e) => {
                                    if (e.key === 'Enter') {
                                        applyFilters({ search });
                                    }
                                }}
                                placeholder="Product name, utility, or state…"
                                className={selectClasses}
                            />
                        </div>
                        <div className="flex flex-col gap-1">
                            <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                Supplier
                            </label>
                            <select
                                value={filters.supplier_id}
                                onChange={(e) =>
                                    applyFilters({
                                        supplier_id: e.target.value,
                                    })
                                }
                                className={selectClasses}
                            >
                                <option value="">All suppliers</option>
                                {suppliers.map((s) => (
                                    <option key={s.id} value={s.id}>
                                        {s.name}
                                    </option>
                                ))}
                            </select>
                        </div>

                        <div className="flex flex-col gap-1">
                            <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                Utility
                            </label>
                            <select
                                value={filters.utility_id}
                                onChange={(e) =>
                                    applyFilters({ utility_id: e.target.value })
                                }
                                className={selectClasses}
                            >
                                <option value="">All utilities</option>
                                {utilities.map((u) => (
                                    <option key={u.id} value={u.id}>
                                        {u.name}
                                    </option>
                                ))}
                            </select>
                        </div>

                        <div className="flex flex-col gap-1">
                            <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                Status
                            </label>
                            <select
                                value={filters.status}
                                onChange={(e) =>
                                    applyFilters({ status: e.target.value })
                                }
                                className={selectClasses}
                            >
                                <option value="">All</option>
                                <option value="pending">Pending</option>
                                <option value="processed">Processed</option>
                            </select>
                        </div>

                        <label className="flex cursor-pointer items-center gap-2 self-end pb-2">
                            <input
                                type="checkbox"
                                checked={showTrashed}
                                onChange={(e) => applyFilters({ trashed: e.target.checked ? '1' : '' })}
                                className="size-4 rounded border-zinc-300 dark:border-zinc-700"
                            />
                            <span className="text-sm text-zinc-700 dark:text-zinc-300">Show archived</span>
                        </label>

                        <button
                            type="button"
                            onClick={() => applyFilters({ search })}
                            className="rounded-md bg-zinc-900 px-3 py-2 text-sm font-medium text-white dark:bg-zinc-100 dark:text-zinc-900"
                        >
                            Search
                        </button>

                        {hasActiveFilters && (
                            <button
                                type="button"
                                onClick={() => {
                                    setSearch('');
                                    applyFilters({
                                        search: '',
                                        status: '',
                                        supplier_id: '',
                                        utility_id: '',
                                        trashed: '',
                                    });
                                }}
                                className="rounded-md px-3 py-2 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                            >
                                Clear
                            </button>
                        )}
                    </div>
                </div>

                {/* Bulk actions */}
                {selectedIds.length > 0 && (
                    <div className="flex items-center justify-between rounded-md border border-zinc-200 bg-zinc-50 px-4 py-2.5 dark:border-zinc-800 dark:bg-zinc-900">
                        <span className="text-sm text-zinc-700 dark:text-zinc-300">
                            {selectedIds.length} selected
                        </span>
                        <div className="flex items-center gap-3">
                            <button
                                type="button"
                                onClick={() => setSelectedIds([])}
                                className="text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                            >
                                Clear selection
                            </button>
                            <button
                                type="button"
                                onClick={() => setBulkArchiveOpen(true)}
                                className="rounded-md border border-red-200 bg-white px-3 py-1.5 text-sm font-medium text-red-600 hover:bg-red-50 dark:border-red-800 dark:bg-zinc-900 dark:text-red-400 dark:hover:bg-red-950"
                            >
                                Archive selected
                            </button>
                        </div>
                    </div>
                )}

                {/* Enrollment Requests table */}
                <div className="overflow-hidden rounded-md border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950">
                    <div className="overflow-x-auto">
                        <table className="w-full text-left text-sm">
                            <thead className="border-b border-zinc-200 text-xs text-zinc-600 uppercase dark:border-zinc-800 dark:text-zinc-400">
                                <tr>
                                    <th className="w-10 px-4 py-3">
                                        <input
                                            type="checkbox"
                                            checked={allSelected}
                                            onChange={toggleSelectAll}
                                            disabled={archivableIds.length === 0}
                                            className="size-4 rounded border-zinc-300 dark:border-zinc-700"
                                            aria-label="Select all"
                                        />
                                    </th>
                                    <SortableHeader label="ID" column="id" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <th className="px-4 py-3">Product</th>
                                    <th className="px-4 py-3">Utility</th>
                                    <th className="px-4 py-3">Supplier</th>
                                    <th className="px-4 py-3">Email</th>
                                    <SortableHeader label="Created" column="created_at" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <SortableHeader label="Status" column="status" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <SortableHeader label="Processed" column="processed_at" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <th className="px-4 py-3">Confirmation</th>
                                    <th className="px-4 py-3" />
                                </tr>
                            </thead>
                            <tbody className="divide-y divide-zinc-200 dark:divide-zinc-800">
                                {enrollmentRequests.data.map((e) => (
                                    <tr
                                        key={e.id}
                                        onClick={() => setSelectedRequest(e)}
                                        className={`cursor-pointer hover:bg-zinc-50 dark:hover:bg-zinc-900 ${e.deleted_at ? 'opacity-60' : ''}`}
                                    >
                                        <td className="px-4 py-3" onClick={(ev) => ev.stopPropagation()}>
                                            {!e.deleted_at && (
                                                <input
                                                    type="checkbox"
                                                    checked={selectedIds.includes(e.id)}
                                                    onChange={() => toggleSelected(e.id)}
                                                    className="size-4 rounded border-zinc-300 dark:border-zinc-700"
                                                    aria-label={`Select enrollment request ${e.id}`}
                                                />
                                            )}
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            {e.id}
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            {productProperName(e.product.name)}
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            {e.product.utility?.name}
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            {e.product.supplier_product?.supplier?.name}
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            <EmailCell email={e.customer_email} isFiltered={e.has_filtered_email_domain} />
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            {formatDateTime(e.created_at, timezone)}
                                        </td>
                                        <td className="px-4 py-3">
                                            <StatusBadge status={e.status} />
                                        </td>
                                        <td className="px-4 py-3 font-medium">
                                            {formatDateTime(e.processed_at, timezone)}
                                        </td>
                                        <td className="px-4 py-3" onClick={(ev) => ev.stopPropagation()}>
                                            {e.confirmation?.pdf_path ? (
                                                <a
                                                    href={confirmationPdf.url([e.id, e.confirmation.id])}
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    className="inline-flex items-center gap-1 rounded-md bg-zinc-100 px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700"
                                                >
                                                    <svg className="size-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                                                        <polyline points="14 2 14 8 20 8"/>
                                                    </svg>
                                                    PDF{e.confirmations_count > 1 ? ` (${e.confirmations_count})` : ''}
                                                </a>
                                            ) : (
                                                <span className="text-xs text-zinc-400">—</span>
                                            )}
                                        </td>
                                        <td className="px-4 py-3 text-right" onClick={(ev) => ev.stopPropagation()}>
                                            <div className="flex justify-end gap-2">
                                                {!e.deleted_at && (
                                                    <>
                                                        <button
                                                            type="button"
                                                            onClick={(ev) => {
                                                                ev.stopPropagation();
                                                                router.post(resendConfirmation.url(e.id), {}, { preserveScroll: true, preserveState: true });
                                                            }}
                                                            className="rounded-md border border-zinc-200 bg-white px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800"
                                                        >
                                                            Resend Confirmation
                                                        </button>

                                                        {e.status !== 'processed' && (
                                                            <button
                                                                type="button"
                                                                onClick={(ev) => {
                                                                    ev.stopPropagation();
                                                                    router.post(build.url(e.id), {}, { preserveState: true });
                                                                }}
                                                                className="rounded-md bg-zinc-900 px-2.5 py-1 text-xs font-medium text-white hover:bg-zinc-800 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-200"
                                                            >
                                                                Build
                                                            </button>
                                                        )}

                                                        {e.status === 'processed' && (
                                                            <button
                                                                type="button"
                                                                onClick={(ev) => {
                                                                    ev.stopPropagation();
                                                                    setRebuildTarget(e);
                                                                }}
                                                                className="rounded-md border border-zinc-200 bg-white px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800"
                                                            >
                                                                Rebuild
                                                            </button>
                                                        )}

                                                        {e.requires_fraud_check && (
                                                            <button
                                                                type="button"
                                                                onClick={(ev) => {
                                                                    ev.stopPropagation();
                                                                    router.post(buildFraudCheck.url(e.id), {}, { preserveScroll: true, preserveState: true });
                                                                }}
                                                                className="rounded-md border border-zinc-200 bg-white px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800"
                                                            >
                                                                Fraud Check
                                                            </button>
                                                        )}

                                                        {e.requires_credit_check && (
                                                            <button
                                                                type="button"
                                                                onClick={(ev) => {
                                                                    ev.stopPropagation();
                                                                    setCreditCheckTarget(e);
                                                                }}
                                                                className="rounded-md border border-zinc-200 bg-white px-2.5 py-1 text-xs font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800"
                                                            >
                                                                Credit Check
                                                            </button>
                                                        )}

                                                        <button
                                                            type="button"
                                                            onClick={(ev) => {
                                                                ev.stopPropagation();
                                                                setArchiveTarget(e);
                                                            }}
                                                            className="rounded-md border border-red-200 bg-white px-2.5 py-1 text-xs font-medium text-red-600 hover:bg-red-50 dark:border-red-800 dark:bg-zinc-900 dark:text-red-400 dark:hover:bg-red-950"
                                                        >
                                                            Archive
                                                        </button>
                                                    </>
                                                )}
                                                {e.deleted_at && (
                                                    <span className="text-xs text-zinc-400 italic">Archived</span>
                                                )}
                                            </div>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>

                    {enrollmentRequests.data.length === 0 && (
                        <div className="p-4 text-sm text-zinc-600 dark:text-zinc-400">
                            No enrollment requests yet.
                        </div>
                    )}
                </div>

                {/* Pagination */}
                {enrollmentRequests.last_page > 1 && (
                    <div className="flex items-center justify-between text-sm">
                        <span className="text-zinc-500 dark:text-zinc-400">
                            Showing{' '}
                            {(enrollmentRequests.current_page - 1) * enrollmentRequests.per_page +
                                1}
                            –
                            {Math.min(
                                enrollmentRequests.current_page * enrollmentRequests.per_page,
                                enrollmentRequests.total,
                            )}{' '}
                            of {enrollmentRequests.total}
                        </span>
                        <div className="flex gap-1">
                            {enrollmentRequests.links.map((link) => (
                                <Link
                                    key={link.label}
                                    href={link.url ?? '#'}
                                    preserveState
                                    className={`rounded-md px-3 py-1.5 text-xs ${
                                        link.active
                                            ? 'bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900'
                                            : link.url
                                              ? 'text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-800'
                                              : 'pointer-events-none text-zinc-300 dark:text-zinc-700'
                                    }`}
                                    dangerouslySetInnerHTML={{
                                        __html: link.label,
                                    }}
                                />
                            ))}
                        </div>
                    </div>
                )}
            </div>
            <EnrollmentRequestDetailModal
                enrollmentRequest={selectedRequest}
                open={selectedRequest !== null}
                onOpenChange={(open) => { if (!open) setSelectedRequest(null); }}
            />
            <ArchiveConfirmDialog
                open={archiveTarget !== null}
                onOpenChange={(open) => { if (!open) setArchiveTarget(null); }}
                onConfirm={confirmArchive}
            />
            <BulkArchiveConfirmDialog
                open={bulkArchiveOpen}
                onOpenChange={setBulkArchiveOpen}
                onConfirm={confirmBulkArchive}
                count={selectedIds.length}
            />
            <RebuildConfirmDialog
                open={rebuildTarget !== null}
                onOpenChange={(open) => { if (!open) setRebuildTarget(null); }}
                onConfirm={confirmRebuild}
                enrollmentRequest={rebuildTarget}
            />
            <CreditCheckModal
                enrollmentRequest={creditCheckTarget}
                open={creditCheckTarget !== null}
                onOpenChange={(open) => { if (!open) setCreditCheckTarget(null); }}
            />
        </AppLayout>
    );
}
