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

import HeadingSmall from '@/components/heading-small';
import { SortableHeader, useSort } from '@/components/sortable-header';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from '@/components/ui/dialog';
import AppLayout from '@/layouts/app-layout';

type Supplier = {
    id: number;
    name: string;
    slug: string;
};

type Mapping = {
    id: number;
    supplier_id: number;
    target_field: string;
    source_path: string;
    cast: string;
    options: Record<string, unknown> | null;
    is_active: boolean;
};

type Props = {
    suppliers: Supplier[];
    activeSupplierId: number | null;
    mappings: Mapping[];
    casts: string[];
    productFields: string[];
};

export default function SupplierProductFieldMappings({
    suppliers,
    activeSupplierId,
    mappings,
    casts,
    productFields,
}: Props) {
    const baseUrl = '/admin/supplier-product-field-mappings';

    const [createOpen, setCreateOpen] = useState(false);
    const [editingId, setEditingId] = useState<number | null>(null);

    const { sorted, sortColumn, sortDirection, toggleSort } = useSort<Mapping>(
        mappings,
        'target_field',
    );

    const breadcrumbs = [
        {
            title: 'Supplier field mappings',
            href:
                activeSupplierId === null
                    ? baseUrl
                    : `${baseUrl}?supplier_id=${activeSupplierId}`,
        },
    ];

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title="Supplier field mappings" />

            <h1 className="sr-only">Supplier field mappings</h1>

            <div className="space-y-6">
                <HeadingSmall
                    title="Supplier field mappings"
                    description="Define how each supplier payload field maps to your canonical product fields."
                />

                <div className="flex flex-col gap-3 sm:flex-row sm:items-end">
                    <div className="flex w-full flex-col gap-1">
                        <label className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
                            Supplier
                        </label>
                        <select
                            className="w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm text-zinc-900 shadow-sm dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100"
                            value={activeSupplierId ?? ''}
                            onChange={(e) => {
                                const supplierId =
                                    e.target.value === ''
                                        ? undefined
                                        : Number(e.target.value);

                                window.location.href =
                                    supplierId === undefined
                                        ? baseUrl
                                        : `${baseUrl}?supplier_id=${supplierId}`;
                            }}
                        >
                            <option value="" disabled>
                                Select supplier
                            </option>
                            {suppliers.map((s) => (
                                <option key={s.id} value={s.id}>
                                    {s.name}
                                </option>
                            ))}
                        </select>
                    </div>

                    <div className="text-sm text-zinc-600 dark:text-zinc-400">
                        Tip: use dotted paths like <code>Rate</code> or{' '}
                        <code>PriceSheet.Rate</code>. Use{' '}
                        <code>{'"static": "value"'}</code> in options to set a
                        fixed value for all products.
                    </div>
                </div>

                {activeSupplierId === null ? (
                    <div className="rounded-md border border-zinc-200 bg-white p-4 text-sm text-zinc-700 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-200">
                        Pick a supplier to view and edit mappings.
                    </div>
                ) : (
                    <div className="space-y-6">
                        <div className="flex items-center justify-between">
                            <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 mapping
                                    </button>
                                </DialogTrigger>

                                <DialogContent className="sm:max-w-2xl">
                                    <DialogHeader>
                                        <DialogTitle>Add mapping</DialogTitle>
                                        <DialogDescription>
                                            Create a new field mapping for this
                                            supplier.
                                        </DialogDescription>
                                    </DialogHeader>

                                    <Form
                                        method="post"
                                        action={baseUrl}
                                        resetOnSuccess
                                        onSuccess={() => setCreateOpen(false)}
                                        transform={(data) => ({
                                            ...data,
                                            supplier_id: activeSupplierId,
                                        })}
                                    >
                                        {({ processing, errors }) => (
                                            <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                                                <div className="flex flex-col gap-1">
                                                    <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                                        Target field
                                                    </label>
                                                    <select
                                                        name="target_field"
                                                        className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                                        defaultValue=""
                                                    >
                                                        <option value="" disabled>
                                                            Select field
                                                        </option>
                                                        {productFields.map((f) => (
                                                            <option key={f} value={f}>
                                                                {f}
                                                            </option>
                                                        ))}
                                                    </select>
                                                    {errors.target_field && (
                                                        <div className="text-xs text-red-600">
                                                            {
                                                                errors.target_field
                                                            }
                                                        </div>
                                                    )}
                                                </div>

                                                <div className="flex flex-col gap-1">
                                                    <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                                        Source path
                                                        <span className="ml-1 font-normal text-zinc-400">
                                                            (or use static in
                                                            options)
                                                        </span>
                                                    </label>
                                                    <input
                                                        name="source_path"
                                                        className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                                        placeholder="ProductDescription"
                                                    />
                                                    {errors.source_path && (
                                                        <div className="text-xs text-red-600">
                                                            {errors.source_path}
                                                        </div>
                                                    )}
                                                </div>

                                                <div className="flex flex-col gap-1">
                                                    <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                                        Cast
                                                    </label>
                                                    <select
                                                        name="cast"
                                                        className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                                        defaultValue="string"
                                                    >
                                                        {casts.map((c) => (
                                                            <option
                                                                key={c}
                                                                value={c}
                                                            >
                                                                {c}
                                                            </option>
                                                        ))}
                                                    </select>
                                                    {errors.cast && (
                                                        <div className="text-xs text-red-600">
                                                            {errors.cast}
                                                        </div>
                                                    )}
                                                </div>

                                                <div className="flex items-end">
                                                    <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
                                                        <input
                                                            type="hidden"
                                                            name="is_active"
                                                            value="0"
                                                        />
                                                        <input
                                                            name="is_active"
                                                            type="checkbox"
                                                            value="1"
                                                            defaultChecked
                                                        />
                                                        Active
                                                    </label>
                                                </div>

                                                <div className="sm:col-span-2">
                                                    <details className="text-sm text-zinc-600 dark:text-zinc-400">
                                                        <summary className="cursor-pointer select-none">
                                                            Advanced options
                                                            (JSON)
                                                        </summary>
                                                        <div className="mt-2">
                                                            <textarea
                                                                name="options_json"
                                                                className="h-28 w-full rounded-md border border-zinc-200 bg-white px-3 py-2 font-mono text-xs dark:border-zinc-800 dark:bg-zinc-950"
                                                                placeholder='{"static": "electric"}  or  {"null_if_blank": true, "map": {"RES": "residential"}}'
                                                            />
                                                            <div className="mt-1 text-xs">
                                                                For now, paste
                                                                JSON here and
                                                                we'll parse it
                                                                server-side.
                                                            </div>
                                                        </div>
                                                    </details>
                                                </div>

                                                <div className="flex items-end justify-end gap-3 sm:col-span-2">
                                                    <button
                                                        type="button"
                                                        onClick={() =>
                                                            setCreateOpen(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={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"
                                                    >
                                                        Add mapping
                                                    </button>
                                                </div>
                                            </div>
                                        )}
                                    </Form>
                                </DialogContent>
                            </Dialog>
                        </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>
                                            <SortableHeader
                                                label="Target"
                                                column="target_field"
                                                sortColumn={sortColumn}
                                                sortDirection={sortDirection}
                                                onSort={toggleSort}
                                            />
                                            <SortableHeader
                                                label="Source / Static"
                                                column="source_path"
                                                sortColumn={sortColumn}
                                                sortDirection={sortDirection}
                                                onSort={toggleSort}
                                            />
                                            <SortableHeader
                                                label="Cast"
                                                column="cast"
                                                sortColumn={sortColumn}
                                                sortDirection={sortDirection}
                                                onSort={toggleSort}
                                            />
                                            <SortableHeader
                                                label="Active"
                                                column="is_active"
                                                sortColumn={sortColumn}
                                                sortDirection={sortDirection}
                                                onSort={toggleSort}
                                            />
                                            <th className="px-4 py-3" />
                                        </tr>
                                    </thead>
                                    <tbody className="divide-y divide-zinc-200 dark:divide-zinc-800">
                                        {sorted.map((m) => (
                                            <tr key={m.id}>
                                                <td className="px-4 py-3 font-mono text-xs">
                                                    {m.target_field}
                                                </td>
                                                <td className="px-4 py-3 font-mono text-xs">
                                                    {m.options !== null &&
                                                    'static' in m.options ? (
                                                        <span className="text-amber-600 dark:text-amber-400">
                                                            ={' '}
                                                            &quot;
                                                            {String(
                                                                m.options.static,
                                                            )}
                                                            &quot;
                                                        </span>
                                                    ) : (
                                                        m.source_path
                                                    )}
                                                </td>
                                                <td className="px-4 py-3 font-mono text-xs">
                                                    {m.cast}
                                                </td>
                                                <td className="px-4 py-3">
                                                    {m.is_active ? 'Yes' : 'No'}
                                                </td>
                                                <td className="px-4 py-3 text-right">
                                                    <div className="flex items-center justify-end gap-4">
                                                        <Dialog
                                                            open={
                                                                editingId === m.id
                                                            }
                                                            onOpenChange={(open) =>
                                                                setEditingId(
                                                                    open
                                                                        ? m.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-2xl">
                                                                <DialogHeader>
                                                                    <DialogTitle>
                                                                        Edit mapping
                                                                    </DialogTitle>
                                                                    <DialogDescription>
                                                                        Update the{' '}
                                                                        {
                                                                            m.target_field
                                                                        }{' '}
                                                                        mapping.
                                                                    </DialogDescription>
                                                                </DialogHeader>

                                                                <Form
                                                                    method="post"
                                                                    action={baseUrl}
                                                                    onSuccess={() =>
                                                                        setEditingId(
                                                                            null,
                                                                        )
                                                                    }
                                                                    transform={(
                                                                        data,
                                                                    ) => ({
                                                                        ...data,
                                                                        supplier_id:
                                                                            activeSupplierId,
                                                                    })}
                                                                >
                                                                    {({
                                                                        processing,
                                                                        errors,
                                                                    }) => (
                                                                        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                                                                            <div className="flex flex-col gap-1">
                                                                                <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                                                                    Target
                                                                                    field
                                                                                </label>
                                                                                <select
                                                                                    name="target_field"
                                                                                    defaultValue={
                                                                                        m.target_field
                                                                                    }
                                                                                    className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                                                                >
                                                                                    {productFields.map((f) => (
                                                                                        <option key={f} value={f}>
                                                                                            {f}
                                                                                        </option>
                                                                                    ))}
                                                                                </select>
                                                                                {errors.target_field && (
                                                                                    <div className="text-xs text-red-600">
                                                                                        {
                                                                                            errors.target_field
                                                                                        }
                                                                                    </div>
                                                                                )}
                                                                            </div>

                                                                            <div className="flex flex-col gap-1">
                                                                                <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                                                                    Source
                                                                                    path
                                                                                    <span className="ml-1 font-normal text-zinc-400">
                                                                                        (or
                                                                                        use
                                                                                        static
                                                                                        in
                                                                                        options)
                                                                                    </span>
                                                                                </label>
                                                                                <input
                                                                                    name="source_path"
                                                                                    defaultValue={
                                                                                        m.source_path ??
                                                                                        ''
                                                                                    }
                                                                                    className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                                                                    placeholder="ProductDescription"
                                                                                />
                                                                                {errors.source_path && (
                                                                                    <div className="text-xs text-red-600">
                                                                                        {
                                                                                            errors.source_path
                                                                                        }
                                                                                    </div>
                                                                                )}
                                                                            </div>

                                                                            <div className="flex flex-col gap-1">
                                                                                <label className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
                                                                                    Cast
                                                                                </label>
                                                                                <select
                                                                                    name="cast"
                                                                                    defaultValue={
                                                                                        m.cast
                                                                                    }
                                                                                    className="rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm dark:border-zinc-800 dark:bg-zinc-950"
                                                                                >
                                                                                    {casts.map(
                                                                                        (
                                                                                            c,
                                                                                        ) => (
                                                                                            <option
                                                                                                key={
                                                                                                    c
                                                                                                }
                                                                                                value={
                                                                                                    c
                                                                                                }
                                                                                            >
                                                                                                {
                                                                                                    c
                                                                                                }
                                                                                            </option>
                                                                                        ),
                                                                                    )}
                                                                                </select>
                                                                                {errors.cast && (
                                                                                    <div className="text-xs text-red-600">
                                                                                        {
                                                                                            errors.cast
                                                                                        }
                                                                                    </div>
                                                                                )}
                                                                            </div>

                                                                            <div className="flex items-end">
                                                                                <label className="flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300">
                                                                                    <input
                                                                                        type="hidden"
                                                                                        name="is_active"
                                                                                        value="0"
                                                                                    />
                                                                                    <input
                                                                                        name="is_active"
                                                                                        type="checkbox"
                                                                                        value="1"
                                                                                        defaultChecked={
                                                                                            m.is_active
                                                                                        }
                                                                                    />
                                                                                    Active
                                                                                </label>
                                                                            </div>

                                                                            <div className="sm:col-span-2">
                                                                                <details className="text-sm text-zinc-600 dark:text-zinc-400">
                                                                                    <summary className="cursor-pointer select-none">
                                                                                        Advanced
                                                                                        options
                                                                                        (JSON)
                                                                                    </summary>
                                                                                    <div className="mt-2">
                                                                                        <textarea
                                                                                            name="options_json"
                                                                                            defaultValue={
                                                                                                m.options
                                                                                                    ? JSON.stringify(
                                                                                                          m.options,
                                                                                                          null,
                                                                                                          2,
                                                                                                      )
                                                                                                    : ''
                                                                                            }
                                                                                            className="h-28 w-full rounded-md border border-zinc-200 bg-white px-3 py-2 font-mono text-xs dark:border-zinc-800 dark:bg-zinc-950"
                                                                                            placeholder='{"static": "electric"}  or  {"null_if_blank": true, "map": {"RES": "residential"}}'
                                                                                        />
                                                                                        <div className="mt-1 text-xs">
                                                                                            For
                                                                                            now,
                                                                                            paste
                                                                                            JSON
                                                                                            here
                                                                                            and
                                                                                            we'll
                                                                                            parse
                                                                                            it
                                                                                            server-side.
                                                                                        </div>
                                                                                    </div>
                                                                                </details>
                                                                            </div>

                                                                            <div className="flex items-end justify-end gap-3 sm:col-span-2">
                                                                                <button
                                                                                    type="button"
                                                                                    onClick={() =>
                                                                                        setEditingId(
                                                                                            null,
                                                                                        )
                                                                                    }
                                                                                    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"
                                                                                >
                                                                                    Save
                                                                                </button>
                                                                            </div>
                                                                        </div>
                                                                    )}
                                                                </Form>
                                                            </DialogContent>
                                                        </Dialog>

                                                        <Form
                                                            method="delete"
                                                            action={`${baseUrl}/${m.id}?supplier_id=${activeSupplierId}`}
                                                        >
                                                            {({ 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>

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

                        <div className="text-sm text-zinc-600 dark:text-zinc-400">
                            <Link
                                href={
                                    activeSupplierId === null
                                        ? baseUrl
                                        : `${baseUrl}?supplier_id=${activeSupplierId}`
                                }
                                className="hover:underline"
                            >
                                Refresh
                            </Link>
                        </div>
                    </div>
                )}
            </div>
        </AppLayout>
    );
}
