import { router } 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 { BrandChip, CatalogStatusBadge } from '@/components/shared/badges';
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 { useCatalogLocale } from '@/hooks/use-catalog-locale';
import { astaraGridTheme } from '@/lib/ag-grid-theme';
import {
    brandLabel,
    formatCount,
    pickLocalizedName,
    updateQuery,
} from '@/lib/catalog';
import { show as bodyTypeShow } from '@/routes/catalog/body-types';
import type {
    CatalogBodyTypeDictionaryEntry,
    CatalogBodyTypesIndexProps,
} from '@/types/catalog';

const SORT_COLUMNS: Record<string, string> = {
    brand: 'brand',
    model_key: 'model_key',
    body_key: 'body_key',
    created: 'created',
};

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

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

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

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

    if (data?.model === null || data?.model === undefined) {
        return (
            <div className="flex h-full items-center text-[11px] text-gray-300">
                —
            </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} · MY {data.model.year}
            </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 CountCell = ({ value }: { value: number }) => (
    <div className="flex h-full items-center text-[11px] font-bold text-astara-purple tabular-nums">
        {formatCount(value)}
    </div>
);

const StatusCell = ({
    data,
}: CustomCellRendererProps<CatalogBodyTypeDictionaryEntry>) => (
    <div className="flex h-full items-center">
        {data?.status !== null && data?.status !== undefined && (
            <CatalogStatusBadge status={data.status} />
        )}
    </div>
);

export function BodyTypesIndexView({
    body_types,
    filters,
    statuses,
}: CatalogBodyTypesIndexProps) {
    const [searchInput, setSearchInput] = useState(filters.search ?? '');
    const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

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

            return [
                {
                    colId: 'brand',
                    headerName: 'Brand',
                    field: 'model.brand.code',
                    width: 110,
                    sortable: true,
                    sort: sort?.colId === 'brand' ? sort.sort : undefined,
                    cellRenderer: BrandCell,
                },
                {
                    colId: 'model_key',
                    headerName: 'Model',
                    field: 'model.name',
                    width: 190,
                    sortable: true,
                    sort: sort?.colId === 'model_key' ? sort.sort : undefined,
                    cellRenderer: ModelCell,
                },
                {
                    colId: 'body_key',
                    headerName: 'Body key',
                    field: 'body_key',
                    width: 150,
                    sortable: true,
                    sort: sort?.colId === 'body_key' ? sort.sort : undefined,
                    cellRenderer: (
                        params: CustomCellRendererProps<CatalogBodyTypeDictionaryEntry>,
                    ) => <KeyCell value={params.data?.body_key ?? null} />,
                },
                {
                    colId: 'name',
                    headerName: 'Name',
                    field: 'name',
                    flex: 2,
                    minWidth: 200,
                    cellRenderer: (
                        params: CustomCellRendererProps<CatalogBodyTypeDictionaryEntry>,
                    ) => (
                        <div className="flex h-full items-center overflow-hidden">
                            <span className="truncate text-xs font-bold text-astara-purple">
                                {params.data?.name}
                            </span>
                        </div>
                    ),
                },
                {
                    colId: 'engines',
                    headerName: 'Engines',
                    field: 'engines_count',
                    width: 95,
                    cellRenderer: (
                        params: CustomCellRendererProps<CatalogBodyTypeDictionaryEntry>,
                    ) => <CountCell value={params.data?.engines_count ?? 0} />,
                },
                {
                    colId: 'trims',
                    headerName: 'Trims',
                    field: 'trims_count',
                    width: 85,
                    cellRenderer: (
                        params: CustomCellRendererProps<CatalogBodyTypeDictionaryEntry>,
                    ) => <CountCell value={params.data?.trims_count ?? 0} />,
                },
                {
                    colId: 'variants',
                    headerName: 'Variants',
                    field: 'variants_count',
                    width: 95,
                    cellRenderer: (
                        params: CustomCellRendererProps<CatalogBodyTypeDictionaryEntry>,
                    ) => <CountCell value={params.data?.variants_count ?? 0} />,
                },
                {
                    colId: 'status',
                    headerName: 'Status',
                    field: 'status',
                    width: 110,
                    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<CatalogBodyTypeDictionaryEntry>,
    ) => {
        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 resetFilters = () => {
        setSearchInput('');
        updateQuery({});
    };

    return (
        <div className="flex flex-1 flex-col overflow-hidden">
            <PageHeader
                title="Body types"
                subtitle="Body-type dictionary — model × year hierarchy"
            />

            <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="relative w-full max-w-md">
                        <Input
                            value={searchInput}
                            onChange={(event) =>
                                setSearchInput(event.target.value)
                            }
                            placeholder="Search body key or name..."
                            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>
                    <StatusSelect
                        statuses={statuses}
                        active={filters.status}
                        onSelect={(status) =>
                            updateQuery({ ...filters, status })
                        }
                    />
                </div>

                {body_types.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 body types 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<CatalogBodyTypeDictionaryEntry>
                                theme={astaraGridTheme}
                                rowData={body_types.data}
                                columnDefs={columnDefs}
                                getRowId={(params) => String(params.data.id)}
                                onCellClicked={(event) => {
                                    if (
                                        event.data?.model !== null &&
                                        event.data?.model !== undefined
                                    ) {
                                        router.visit(
                                            bodyTypeShow({
                                                model: event.data.model.id,
                                                bodyType: event.data.id,
                                            }),
                                        );
                                    }
                                }}
                                onSortChanged={onSortChanged}
                                rowClass="cursor-pointer"
                                rowHeight={40}
                                headerHeight={36}
                                suppressCellFocus
                                defaultColDef={{ resizable: true }}
                            />
                        </div>
                        <Pagination
                            links={body_types.links}
                            meta={body_types.meta}
                        />
                    </div>
                )}
            </div>
        </div>
    );
}
