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

import { index as enrollmentRequestsIndex } from '@/actions/App/Http/Controllers/Admin/EnrollmentRequestController';
import HeadingSmall from '@/components/heading-small';
import { useUserTimezone } from '@/hooks/use-user-timezone';
import AppLayout from '@/layouts/app-layout';
import { formatDateTime } from '@/lib/format-date';
import {
    index as webFormSessionsIndex,
    show as webFormSessionsShow,
} from '@/routes/admin/web-form-sessions';

type EnrollmentRequest = {
    id: number;
    status: string | null;
};

type WebFormProgressEvent = {
    id: number;
    event_type: string;
    field_name: string | null;
    sequence: number | null;
    meta: Record<string, unknown> | null;
    occurred_at: string | null;
    created_at: string;
};

type FieldValue = {
    field_name: string;
    value: unknown;
    event_type: string;
    sequence: number | null;
    occurred_at: string | null;
};

type WebFormSession = {
    id: number;
    session_id: string;
    web_form_identifier: string | null;
    web_form_type: string | null;
    product_id: number | null;
    enrollment_id: number | null;
    ip_address: string | null;
    utm: Record<string, string> | null;
    user_agent: string | null;
    started_at: string | null;
    last_event_at: string | null;
    submitted_at: string | null;
    enrollment_request_id: number | null;
    enrollment_request: EnrollmentRequest | null;
};

type PaginatedEvents = {
    data: WebFormProgressEvent[];
    current_page: number;
    last_page: number;
    per_page: number;
    total: number;
    links: { url: string | null; label: string; active: boolean }[];
};

type Filters = {
    search: string;
    event_type: string;
    field_name: string;
    sort_by: string;
    sort_direction: string;
};

type Props = {
    session: WebFormSession;
    fieldValues: FieldValue[];
    events: PaginatedEvents;
    filters: Filters;
};

function StateBadge({ submittedAt }: { submittedAt: string | null }) {
    return submittedAt ? (
        <span className="inline-block rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-300">
            Submitted
        </span>
    ) : (
        <span className="inline-block rounded-full bg-zinc-100 px-2 py-0.5 text-xs font-medium text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400">
            Abandoned
        </span>
    );
}

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';

function formatFieldValue(value: unknown): string {
    if (value === null || value === undefined || value === '') {
        return '—';
    }

    if (typeof value === 'string') {
        return value;
    }

    return JSON.stringify(value);
}

export default function WebFormSessionShow({
    session,
    fieldValues,
    events,
    filters,
}: Props) {
    const timezone = useUserTimezone();
    const [search, setSearch] = useState(filters.search);

    const breadcrumbs = [
        { title: 'Web Form Sessions', href: webFormSessionsIndex.url() },
        {
            title: session.session_id,
            href: webFormSessionsShow.url(session.id),
        },
    ];

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

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

    const hasActiveFilters =
        filters.search || filters.event_type || filters.field_name;

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title={`Web Form Session ${session.session_id}`} />

            <div className="space-y-6">
                <div className="flex items-center gap-3">
                    <HeadingSmall
                        title={session.session_id}
                        description={`${session.web_form_identifier ?? '—'} · ${session.web_form_type ?? '—'}`}
                    />
                    <StateBadge submittedAt={session.submitted_at} />
                </div>

                <dl className="divide-y divide-zinc-100 rounded-md border border-zinc-200 bg-white px-4 dark:divide-zinc-800 dark:border-zinc-800 dark:bg-zinc-950">
                    {(
                        [
                            ['Product', session.product_id ?? '—'],
                            ['IP Address', session.ip_address ?? '—'],
                            ['User Agent', session.user_agent ?? '—'],
                            [
                                'UTM Parameters',
                                session.utm &&
                                Object.keys(session.utm).length > 0 ? (
                                    <div className="space-y-1">
                                        {Object.entries(session.utm).map(
                                            ([key, value]) => (
                                                <div
                                                    key={key}
                                                    className="flex gap-2"
                                                >
                                                    <span className="font-mono text-xs text-zinc-500 dark:text-zinc-400">
                                                        {key}:
                                                    </span>
                                                    <span className="font-mono text-xs">
                                                        {value}
                                                    </span>
                                                </div>
                                            ),
                                        )}
                                    </div>
                                ) : (
                                    <span className="text-zinc-400">—</span>
                                ),
                            ],
                            [
                                'Started',
                                formatDateTime(session.started_at, timezone, {
                                    includeSeconds: true,
                                }),
                            ],
                            [
                                'Last Event',
                                formatDateTime(
                                    session.last_event_at,
                                    timezone,
                                    { includeSeconds: true },
                                ),
                            ],
                            [
                                'Submitted',
                                formatDateTime(
                                    session.submitted_at,
                                    timezone,
                                    { includeSeconds: true },
                                ),
                            ],
                            [
                                'Enrollment Request',
                                session.enrollment_request_id ? (
                                    <Link
                                        href={enrollmentRequestsIndex.url({
                                            query: {
                                                id: String(
                                                    session.enrollment_request_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"
                                    >
                                        #{session.enrollment_request_id} ·{' '}
                                        {session.enrollment_request?.status ??
                                            '—'}{' '}
                                        →
                                    </Link>
                                ) : (
                                    <span className="text-zinc-400">None</span>
                                ),
                            ],
                        ] as [string, React.ReactNode][]
                    ).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>

                <div className="space-y-3">
                    <h2 className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
                        Consolidated Field Values
                    </h2>

                    <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="px-4 py-3">Field</th>
                                        <th className="px-4 py-3">
                                            Latest Value
                                        </th>
                                        <th className="px-4 py-3">
                                            Recorded Via
                                        </th>
                                        <th className="px-4 py-3">
                                            Occurred
                                        </th>
                                    </tr>
                                </thead>
                                <tbody className="divide-y divide-zinc-200 dark:divide-zinc-800">
                                    {fieldValues.map((fieldValue) => (
                                        <tr key={fieldValue.field_name}>
                                            <td className="px-4 py-3 font-medium">
                                                {fieldValue.field_name}
                                            </td>
                                            <td className="px-4 py-3 font-mono text-xs break-all text-zinc-900 dark:text-zinc-100">
                                                {formatFieldValue(
                                                    fieldValue.value,
                                                )}
                                            </td>
                                            <td className="px-4 py-3 text-zinc-600 dark:text-zinc-400">
                                                {fieldValue.event_type}
                                            </td>
                                            <td className="px-4 py-3">
                                                {formatDateTime(
                                                    fieldValue.occurred_at,
                                                    timezone,
                                                    { includeSeconds: true },
                                                )}
                                            </td>
                                        </tr>
                                    ))}
                                </tbody>
                            </table>
                        </div>

                        {fieldValues.length === 0 && (
                            <div className="p-4 text-sm text-zinc-600 dark:text-zinc-400">
                                No field values recorded for this session yet.
                            </div>
                        )}
                    </div>
                </div>

                <div className="space-y-3">
                    <div className="flex items-center justify-between">
                        <h2 className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
                            Progress Events
                        </h2>

                        <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-52">
                                <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="Search event type or field…"
                                    className={selectClasses}
                                />
                            </div>

                            <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: '',
                                            event_type: '',
                                            field_name: '',
                                        });
                                    }}
                                    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>

                    <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="px-4 py-3">Seq</th>
                                        <th className="px-4 py-3">Type</th>
                                        <th className="px-4 py-3">Field</th>
                                        <th className="px-4 py-3">Meta</th>
                                        <th className="px-4 py-3">Occurred</th>
                                    </tr>
                                </thead>
                                <tbody className="divide-y divide-zinc-200 dark:divide-zinc-800">
                                    {events.data.map((event) => (
                                        <tr key={event.id}>
                                            <td className="px-4 py-3 text-zinc-600 dark:text-zinc-400">
                                                {event.sequence ?? '—'}
                                            </td>
                                            <td className="px-4 py-3 font-medium">
                                                {event.event_type}
                                            </td>
                                            <td className="px-4 py-3 text-zinc-600 dark:text-zinc-400">
                                                {event.field_name ?? '—'}
                                            </td>
                                            <td className="px-4 py-3">
                                                {event.meta ? (
                                                    <pre className="max-w-md overflow-auto font-mono text-xs whitespace-pre-wrap text-zinc-600 dark:text-zinc-400">
                                                        {JSON.stringify(
                                                            event.meta,
                                                            null,
                                                            2,
                                                        )}
                                                    </pre>
                                                ) : (
                                                    <span className="text-zinc-400">
                                                        —
                                                    </span>
                                                )}
                                            </td>
                                            <td className="px-4 py-3">
                                                {formatDateTime(
                                                    event.occurred_at ??
                                                        event.created_at,
                                                    timezone,
                                                    { includeSeconds: true },
                                                )}
                                            </td>
                                        </tr>
                                    ))}
                                </tbody>
                            </table>
                        </div>

                        {events.data.length === 0 && (
                            <div className="p-4 text-sm text-zinc-600 dark:text-zinc-400">
                                No progress events recorded for this session.
                            </div>
                        )}
                    </div>

                    {events.last_page > 1 && (
                        <div className="flex items-center justify-between text-sm">
                            <span className="text-zinc-500 dark:text-zinc-400">
                                Showing{' '}
                                {(events.current_page - 1) * events.per_page +
                                    1}
                                –
                                {Math.min(
                                    events.current_page * events.per_page,
                                    events.total,
                                )}{' '}
                                of {events.total}
                            </span>
                            <div className="flex gap-1">
                                {events.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>
            </div>
        </AppLayout>
    );
}
