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

import HeadingSmall from '@/components/heading-small';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from '@/components/ui/dialog';
import AppLayout from '@/layouts/app-layout';
import { index, store, update, destroy } from '@/routes/admin/zip-codes';
import { index as utilitiesIndex } from '@/routes/admin/zip-codes/utilities';

type State = {
    id: number;
    code: string;
    name: string;
};

type ZipCode = {
    id: number;
    zipcode: string;
    plus4: string | null;
    place_name: string | null;
    country_code: string;
    state_id: number;
    state: State | null;
};

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

type Filters = {
    search: string;
    state_id: string;
};

type Props = {
    zipCodes: PaginatedZipCodes;
    states: State[];
    filters: Filters;
};

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

function ZipCodeForm({
    states,
    defaults,
    onSuccess,
    onCancel,
    action,
    method,
    submitLabel,
}: {
    states: State[];
    defaults?: Partial<ZipCode>;
    onSuccess: () => void;
    onCancel: () => void;
    action: string;
    method: 'post' | 'put';
    submitLabel: string;
}) {
    return (
        <Form method={method} action={action} resetOnSuccess onSuccess={onSuccess}>
            {({ processing, errors }) => (
                <div className="grid grid-cols-1 gap-3">
                    <div className="grid grid-cols-2 gap-3">
                        <div className="flex flex-col gap-1">
                            <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                Zip Code
                            </label>
                            <input
                                name="zipcode"
                                defaultValue={defaults?.zipcode ?? ''}
                                maxLength={5}
                                className="rounded-md border border-zinc-200 bg-white px-3 py-2 font-mono text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                placeholder="12345"
                            />
                            {errors.zipcode && (
                                <div className="text-xs text-red-600">{errors.zipcode}</div>
                            )}
                        </div>

                        <div className="flex flex-col gap-1">
                            <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                Plus4
                            </label>
                            <input
                                name="plus4"
                                defaultValue={defaults?.plus4 ?? ''}
                                maxLength={4}
                                className="rounded-md border border-zinc-200 bg-white px-3 py-2 font-mono text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                placeholder="6789"
                            />
                            {errors.plus4 && (
                                <div className="text-xs text-red-600">{errors.plus4}</div>
                            )}
                        </div>
                    </div>

                    <div className="flex flex-col gap-1">
                        <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                            City / Place Name
                        </label>
                        <input
                            name="place_name"
                            defaultValue={defaults?.place_name ?? ''}
                            className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                            placeholder="Springfield"
                        />
                        {errors.place_name && (
                            <div className="text-xs text-red-600">{errors.place_name}</div>
                        )}
                    </div>

                    <div className="flex flex-col gap-1">
                        <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                            State
                        </label>
                        <select
                            name="state_id"
                            defaultValue={defaults?.state_id ?? ''}
                            className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                        >
                            <option value="">Select a state…</option>
                            {states.map((s) => (
                                <option key={s.id} value={s.id}>
                                    {s.code} — {s.name}
                                </option>
                            ))}
                        </select>
                        {errors.state_id && (
                            <div className="text-xs text-red-600">{errors.state_id}</div>
                        )}
                    </div>

                    <div className="flex flex-col gap-1">
                        <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                            Country Code
                        </label>
                        <input
                            name="country_code"
                            defaultValue={defaults?.country_code ?? 'US'}
                            maxLength={2}
                            className="rounded-md border border-zinc-200 bg-white px-3 py-2 font-mono text-sm uppercase dark:border-zinc-800 dark:bg-zinc-950"
                            placeholder="US"
                        />
                        {errors.country_code && (
                            <div className="text-xs text-red-600">{errors.country_code}</div>
                        )}
                    </div>

                    <div className="flex items-end justify-end gap-3">
                        <button
                            type="button"
                            onClick={onCancel}
                            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={processing}
                            className="rounded-md bg-zinc-900 px-3 py-2 text-sm font-medium text-white disabled:opacity-60 dark:bg-zinc-100 dark:text-zinc-900"
                        >
                            {submitLabel}
                        </button>
                    </div>
                </div>
            )}
        </Form>
    );
}

export default function ZipCodes({ zipCodes, states, filters }: Props) {
    const [editingId, setEditingId] = useState<number | null>(null);
    const [createOpen, setCreateOpen] = useState(false);
    const [search, setSearch] = useState(filters.search);
    const [stateId, setStateId] = useState(filters.state_id);
    const searchTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);

    useEffect(() => {
        if (searchTimeout.current) {
            clearTimeout(searchTimeout.current);
        }
        searchTimeout.current = setTimeout(() => {
            router.get(
                index.url(),
                { search, state_id: stateId },
                { preserveState: true, replace: true },
            );
        }, 350);
        return () => {
            if (searchTimeout.current) clearTimeout(searchTimeout.current);
        };
    }, [search, stateId]);

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title="Zip Codes" />

            <h1 className="sr-only">Zip Codes</h1>

            <div className="space-y-6">
                <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
                    <HeadingSmall
                        title="Zip Codes"
                        description="Manage the zip codes available in the energy market."
                    />

                    <Dialog open={createOpen} onOpenChange={setCreateOpen}>
                        <DialogTrigger asChild>
                            <button
                                type="button"
                                className="rounded-md bg-zinc-900 px-3 py-2 text-sm font-medium text-white dark:bg-zinc-100 dark:text-zinc-900"
                            >
                                Add zip code
                            </button>
                        </DialogTrigger>

                        <DialogContent className="sm:max-w-md">
                            <DialogHeader>
                                <DialogTitle>Add zip code</DialogTitle>
                                <DialogDescription>
                                    Create a new zip code for the energy market.
                                </DialogDescription>
                            </DialogHeader>

                            <ZipCodeForm
                                states={states}
                                action={store.url()}
                                method="post"
                                submitLabel="Add zip code"
                                onSuccess={() => setCreateOpen(false)}
                                onCancel={() => setCreateOpen(false)}
                            />
                        </DialogContent>
                    </Dialog>
                </div>

                <div className="flex gap-3">
                    <input
                        type="search"
                        value={search}
                        onChange={(e) => setSearch(e.target.value)}
                        placeholder="Search by zip or city…"
                        className="w-64 rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                    />
                    <select
                        value={stateId}
                        onChange={(e) => setStateId(e.target.value)}
                        className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                    >
                        <option value="">All states</option>
                        {states.map((s) => (
                            <option key={s.id} value={s.id}>
                                {s.code} — {s.name}
                            </option>
                        ))}
                    </select>
                    {(search || stateId) && (
                        <button
                            type="button"
                            onClick={() => {
                                setSearch('');
                                setStateId('');
                            }}
                            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 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 uppercase text-zinc-600 dark:border-zinc-800 dark:text-zinc-400">
                                <tr>
                                    <th className="px-4 py-3">Zip Code</th>
                                    <th className="px-4 py-3">Plus4</th>
                                    <th className="px-4 py-3">City</th>
                                    <th className="px-4 py-3">State</th>
                                    <th className="px-4 py-3">Country</th>
                                    <th className="px-4 py-3" />
                                </tr>
                            </thead>
                            <tbody className="divide-y divide-zinc-200 dark:divide-zinc-800">
                                {zipCodes.data.map((z) => (
                                    <tr key={z.id}>
                                        <td className="px-4 py-3 font-mono text-xs font-medium">
                                            {z.zipcode}
                                        </td>
                                        <td className="px-4 py-3 font-mono text-xs text-zinc-500">
                                            {z.plus4 ?? '—'}
                                        </td>
                                        <td className="px-4 py-3">{z.place_name ?? '—'}</td>
                                        <td className="px-4 py-3 font-mono text-xs">
                                            {z.state?.code ?? '—'}
                                        </td>
                                        <td className="px-4 py-3 font-mono text-xs uppercase">
                                            {z.country_code}
                                        </td>
                                        <td className="px-4 py-3 text-right">
                                            <div className="flex items-center justify-end gap-4">
                                                <Link
                                                    href={utilitiesIndex.url(z.id)}
                                                    className="text-sm text-zinc-700 hover:underline dark:text-zinc-300"
                                                >
                                                    Utilities
                                                </Link>

                                                <Dialog
                                                    open={editingId === z.id}
                                                    onOpenChange={(open) =>
                                                        setEditingId(open ? z.id : null)
                                                    }
                                                >
                                                    <DialogTrigger asChild>
                                                        <button
                                                            type="button"
                                                            className="text-sm text-zinc-700 hover:underline dark:text-zinc-300"
                                                        >
                                                            Edit
                                                        </button>
                                                    </DialogTrigger>

                                                    <DialogContent className="sm:max-w-md">
                                                        <DialogHeader>
                                                            <DialogTitle>Edit zip code</DialogTitle>
                                                            <DialogDescription>
                                                                Update {z.zipcode} settings.
                                                            </DialogDescription>
                                                        </DialogHeader>

                                                        <ZipCodeForm
                                                            states={states}
                                                            defaults={z}
                                                            action={update.url(z.id)}
                                                            method="put"
                                                            submitLabel="Save"
                                                            onSuccess={() => setEditingId(null)}
                                                            onCancel={() => setEditingId(null)}
                                                        />
                                                    </DialogContent>
                                                </Dialog>

                                                <Form method="delete" action={destroy.url(z.id)}>
                                                    {({ processing }) => (
                                                        <button
                                                            type="submit"
                                                            disabled={processing}
                                                            className="text-sm text-red-700 hover:underline disabled:opacity-60 dark:text-red-400"
                                                        >
                                                            Delete
                                                        </button>
                                                    )}
                                                </Form>
                                            </div>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>

                    {zipCodes.data.length === 0 && (
                        <div className="p-4 text-sm text-zinc-600 dark:text-zinc-400">
                            No zip codes found.
                        </div>
                    )}
                </div>

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