import { Deferred, router, usePage } from '@inertiajs/react';
import type { ColDef, SortChangedEvent } from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import type { CustomCellRendererProps } from 'ag-grid-react';
import { RefreshCcw, Search } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { CatalogStatusBadge } from '@/components/shared/badges';
import { BrandChip } from '@/components/shared/badges';
import { BrandTags } from '@/components/shared/brand-tags';
import { EmptyState } from '@/components/shared/empty-state';
import { LocaleFallbackChip } from '@/components/shared/locale-chips';
import { PageHeader } from '@/components/shared/page-header';
import { Pagination } from '@/components/shared/pagination';
import { StatusSelect } from '@/components/shared/status-select';
import { Input } from '@/components/ui/input';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { useCatalogLocale } from '@/hooks/use-catalog-locale';
import { astaraGridTheme } from '@/lib/ag-grid-theme';
import {
    brandLabel,
    formatPrice,
    isPriceSentinel,
    pickLocalizedName,
    updateQuery,
} from '@/lib/catalog';
import { cn } from '@/lib/utils';
import { show as variantShow } from '@/routes/catalog/variants';
import type {
    CatalogBodyTypeOption,
    CatalogVariant,
    CatalogVariantsIndexProps,
} from '@/types/catalog';

const SORT_COLUMNS: Record<string, string> = {
    name: 'name',
    price: 'price',
    brand: 'brand',
    model: 'model_key',
};

/*
 * Body-type filter — options arrive via a deferred prop (`body_types`), so
 * the select renders a skeleton until the background partial request lands.
 * The resolved data is read from the page props (in v3 the Deferred slot
 * only exposes `reloading`).
 */
function BodyTypeFilterSlot({
    models,
    filters,
}: {
    models: CatalogVariantsIndexProps['models'];
    filters: CatalogVariantsIndexProps['filters'];
}) {
    const { props } = usePage<{ body_types: CatalogBodyTypeOption[] }>();
    const bodyTypes = props.body_types ?? [];

    return (
        <BodyTypeFilter
            bodyTypes={bodyTypes}
            models={models}
            filters={filters}
        />
    );
}

function BodyTypeFilter({
    bodyTypes,
    models,
    filters,
}: {
    bodyTypes: CatalogBodyTypeOption[];
    models: CatalogVariantsIndexProps['models'];
    filters: CatalogVariantsIndexProps['filters'];
}) {
    const brandModels = models.filter(
        (model) => !filters.brand || model.brand_code === filters.brand,
    );

    const bodyTypeModelIds = new Set(
        filters.model !== null
            ? [filters.model]
            : brandModels.map((model) => model.id),
    );

    const filteredBodyTypes = bodyTypes.filter((bodyType) =>
        bodyTypeModelIds.has(bodyType.model_id),
    );

    return (
        <Select
            value={
                filters.body_type !== null ? String(filters.body_type) : 'all'
            }
            onValueChange={(value) =>
                updateQuery({
                    ...filters,
                    body_type: value === 'all' ? null : Number(value),
                })
            }
        >
            <SelectTrigger size="sm" className="w-56 bg-white text-xs">
                <SelectValue placeholder="All body types" />
            </SelectTrigger>
            <SelectContent>
                <SelectItem value="all">All body types</SelectItem>
                {filteredBodyTypes.map((bodyType) => (
                    <SelectItem key={bodyType.id} value={String(bodyType.id)}>
                        {bodyType.body_key} — {bodyType.name}
                    </SelectItem>
                ))}
            </SelectContent>
        </Select>
    );
}

function initialSort(filters: CatalogVariantsIndexProps['filters']) {
    const colId = Object.entries(SORT_COLUMNS).find(
        ([, value]) => value === filters.sort,
    )?.[0];

    return colId
        ? {
              colId,
              sort: filters.direction ?? 'asc',
          }
        : null;
}

const NameCell = ({ data }: CustomCellRendererProps<CatalogVariant>) => (
    <div className="flex h-full items-center overflow-hidden">
        <span className="truncate text-xs font-bold text-astara-purple">
            {data?.name}
        </span>
    </div>
);

const BrandCell = ({ data }: CustomCellRendererProps<CatalogVariant>) => (
    <div className="flex h-full items-center">
        {data?.brand && <BrandChip label={brandLabel(data.brand.code)} />}
    </div>
);

const ModelCell = ({ data }: CustomCellRendererProps<CatalogVariant>) => {
    const locale = useCatalogLocale();

    if (data?.model === null || data?.model === undefined) {
        return (
            <div className="flex h-full flex-col justify-center overflow-hidden">
                <span className="truncate text-[11px] font-bold text-astara-purple">
                    —
                </span>
            </div>
        );
    }

    const modelName = pickLocalizedName(data.model, locale, data.model.name);

    return (
        <div className="flex h-full flex-col justify-center overflow-hidden">
            <div className="flex items-center gap-1.5 overflow-hidden">
                <span className="truncate text-[11px] font-bold text-astara-purple">
                    {modelName.text}
                </span>
                {modelName.fellBack && (
                    <LocaleFallbackChip
                        requested={locale}
                        used={modelName.locale}
                    />
                )}
            </div>
            <span className="truncate text-[9px] font-semibold text-gray-400">
                {data.model.model_key}
            </span>
        </div>
    );
};

const KeyCell = ({ value }: { value: string | null }) => (
    <div className="flex h-full items-center font-mono text-[10px] text-gray-500">
        {value ?? '—'}
    </div>
);

const PriceCell = ({ data }: CustomCellRendererProps<CatalogVariant>) => {
    if (data === undefined) {
        return null;
    }

    // P013: missing price renders "–" (never a formatted 0); sentinel
    // styling stays for 0.00 / 99999.00 present as data.
    const price = data.price ?? null;

    if (price === null) {
        return (
            <div className="flex h-full items-center justify-end">
                <span className="text-[11px] text-gray-300">–</span>
            </div>
        );
    }

    const sentinel = isPriceSentinel(price);

    return (
        <div className="flex h-full items-center justify-end gap-1">
            <span
                className={cn(
                    'text-[11px] font-bold tabular-nums',
                    sentinel ? 'text-amber-600' : 'text-gray-600',
                )}
            >
                {formatPrice(price)}
            </span>
            {sentinel && (
                <span className="rounded bg-amber-50 px-1 py-0.5 text-[8px] font-bold tracking-wider text-amber-600 uppercase">
                    sentinel
                </span>
            )}
        </div>
    );
};

const StatusCell = ({ data }: CustomCellRendererProps<CatalogVariant>) => (
    <div className="flex h-full items-center">
        {data && <CatalogStatusBadge status={data.status} />}
    </div>
);

export function VariantsIndexView({
    variants,
    filters,
    brands,
    models,
    statuses,
}: CatalogVariantsIndexProps) {
    const [searchInput, setSearchInput] = useState(filters.search ?? '');
    const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

    const brandModels = models.filter(
        (model) => !filters.brand || model.brand_code === filters.brand,
    );

    const [columnDefs] = useState<ColDef<CatalogVariant>[]>(() => {
        const sort = initialSort(filters);

        return [
            {
                colId: 'name',
                headerName: 'Name',
                field: 'name',
                flex: 2,
                minWidth: 220,
                sortable: true,
                sort: sort?.colId === 'name' ? sort.sort : undefined,
                cellRenderer: NameCell,
            },
            {
                colId: 'brand',
                headerName: 'Brand',
                field: 'brand.code',
                width: 120,
                sortable: true,
                sort: sort?.colId === 'brand' ? sort.sort : undefined,
                cellRenderer: BrandCell,
            },
            {
                colId: 'model',
                headerName: 'Model',
                field: 'model.name',
                width: 180,
                sortable: true,
                sort: sort?.colId === 'model' ? sort.sort : undefined,
                cellRenderer: ModelCell,
            },
            {
                colId: 'year',
                headerName: 'Year',
                field: 'model_year.year_key',
                width: 90,
                cellRenderer: (
                    params: CustomCellRendererProps<CatalogVariant>,
                ) => (
                    <KeyCell
                        value={params.data?.model_year?.year_key ?? null}
                    />
                ),
            },
            {
                colId: 'body_type',
                headerName: 'Body type',
                field: 'body_type.body_key',
                width: 110,
                cellRenderer: (
                    params: CustomCellRendererProps<CatalogVariant>,
                ) => (
                    <KeyCell value={params.data?.body_type?.body_key ?? null} />
                ),
            },
            {
                colId: 'trim',
                headerName: 'Trim',
                field: 'trim.trim_key',
                width: 130,
                cellRenderer: (
                    params: CustomCellRendererProps<CatalogVariant>,
                ) => <KeyCell value={params.data?.trim?.trim_key ?? null} />,
            },
            {
                colId: 'engine',
                headerName: 'Engine',
                field: 'engine.engine_key',
                width: 130,
                cellRenderer: (
                    params: CustomCellRendererProps<CatalogVariant>,
                ) => (
                    <KeyCell value={params.data?.engine?.engine_key ?? null} />
                ),
            },
            {
                colId: 'price',
                headerName: 'Price',
                field: 'price',
                width: 150,
                sortable: true,
                sort: sort?.colId === 'price' ? sort.sort : undefined,
                cellRenderer: PriceCell,
            },
            {
                colId: 'status',
                headerName: 'Status',
                field: 'status',
                width: 120,
                cellRenderer: StatusCell,
            },
        ];
    });

    useEffect(() => {
        if (debounceRef.current) {
            clearTimeout(debounceRef.current);
        }

        debounceRef.current = setTimeout(() => {
            if (searchInput !== filters.search) {
                updateQuery(
                    { ...filters, search: searchInput || null },
                    { preserveState: true, replace: true },
                );
            }
        }, 300);

        return () => {
            if (debounceRef.current) {
                clearTimeout(debounceRef.current);
            }
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [searchInput]);

    const onSortChanged = (event: SortChangedEvent<CatalogVariant>) => {
        if (event.source === 'api') {
            return;
        }

        const sorted = event.api
            .getColumnState()
            .find(
                (column) => column.sort !== undefined && column.sort !== null,
            );

        updateQuery({
            ...filters,
            sort: sorted ? SORT_COLUMNS[sorted.colId] : null,
            direction: sorted?.sort ?? null,
        });
    };

    const onCellClicked = (event: {
        colDef?: { colId?: string };
        data?: CatalogVariant;
    }) => {
        if (!event.data) {
            return;
        }

        router.visit(variantShow({ variant: event.data.id }));
    };

    const resetFilters = () => {
        setSearchInput('');
        updateQuery({});
    };

    return (
        <div className="flex flex-1 flex-col overflow-hidden">
            <PageHeader
                title="Variants"
                subtitle="Saleable trim × engine combinations"
            />

            <div className="custom-scroll flex-1 overflow-y-auto p-4 md:p-6">
                <div className="mb-4 flex flex-col gap-3">
                    <div className="flex flex-wrap items-center gap-3">
                        <div className="relative w-full max-w-md">
                            <Input
                                value={searchInput}
                                onChange={(event) =>
                                    setSearchInput(event.target.value)
                                }
                                placeholder="Search name, engine or trim..."
                                className="bg-white py-2 pr-3 pl-9 text-xs"
                            />
                            <Search
                                size={14}
                                className="absolute top-2.5 left-3 text-gray-400"
                            />
                        </div>
                        <Select
                            value={
                                filters.model !== null
                                    ? String(filters.model)
                                    : 'all'
                            }
                            onValueChange={(value) =>
                                updateQuery({
                                    ...filters,
                                    model:
                                        value === 'all' ? null : Number(value),
                                    body_type: null,
                                })
                            }
                        >
                            <SelectTrigger
                                size="sm"
                                className="w-56 bg-white text-xs"
                            >
                                <SelectValue placeholder="All models" />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectItem value="all">All models</SelectItem>
                                {brandModels.map((model) => (
                                    <SelectItem
                                        key={model.id}
                                        value={String(model.id)}
                                    >
                                        {brandLabel(model.brand_code)} —{' '}
                                        {model.model_key}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                        <Deferred
                            data="body_types"
                            fallback={
                                <div className="h-9 w-56 animate-pulse rounded-md bg-gray-100" />
                            }
                        >
                            <BodyTypeFilterSlot
                                models={models}
                                filters={filters}
                            />
                        </Deferred>
                    </div>
                    <BrandTags
                        brands={brands}
                        active={filters.brand}
                        onSelect={(brand) =>
                            updateQuery({
                                ...filters,
                                brand,
                                model: null,
                                body_type: null,
                            })
                        }
                    />
                    <StatusSelect
                        statuses={statuses}
                        active={filters.status}
                        onSelect={(status) =>
                            updateQuery({ ...filters, status })
                        }
                    />
                </div>

                {variants.meta.total === 0 ? (
                    <div className="rounded-xl border border-[rgba(30,25,50,0.06)] bg-white shadow-[0_2px_8px_rgba(30,25,50,0.04)]">
                        <EmptyState
                            title="No variants match the current filters"
                            description="Adjust the search, brand, model or status filters — or reset everything."
                            action={
                                <button
                                    type="button"
                                    onClick={resetFilters}
                                    className="inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-astara-orange px-4 py-2 text-[10px] font-bold tracking-widest text-white uppercase transition-all hover:bg-astara-orange-hover"
                                >
                                    <RefreshCcw size={12} />
                                    Reset filters
                                </button>
                            }
                        />
                    </div>
                ) : (
                    <div className="flex flex-col overflow-hidden rounded-xl border border-[rgba(30,25,50,0.06)] bg-white shadow-[0_2px_8px_rgba(30,25,50,0.04)]">
                        <div className="h-[560px]">
                            <AgGridReact<CatalogVariant>
                                theme={astaraGridTheme}
                                rowData={variants.data}
                                columnDefs={columnDefs}
                                getRowId={(params) => String(params.data.id)}
                                onCellClicked={onCellClicked}
                                onSortChanged={onSortChanged}
                                rowClass="cursor-pointer"
                                rowHeight={40}
                                headerHeight={36}
                                suppressCellFocus
                                defaultColDef={{ resizable: true }}
                            />
                        </div>
                        <Pagination
                            links={variants.links}
                            meta={variants.meta}
                        />
                    </div>
                )}
            </div>
        </div>
    );
}
