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 { 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 { useCatalogLocale } from '@/hooks/use-catalog-locale';
import { astaraGridTheme } from '@/lib/ag-grid-theme';
import { brandLabel, pickLocalizedName, updateQuery } from '@/lib/catalog';
import { show as modelShow } from '@/routes/catalog/models';
import type { CatalogModel, CatalogModelsIndexProps } from '@/types/catalog';

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

function initialSort(filters: CatalogModelsIndexProps['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<CatalogModel>) => (
    <div className="flex h-full items-center">
        {data && <BrandChip label={brandLabel(data.brand.code)} />}
    </div>
);

const NameCell = ({ data }: CustomCellRendererProps<CatalogModel>) => {
    const locale = useCatalogLocale();

    if (!data) {
        return null;
    }

    const resolved = pickLocalizedName(data, locale, data.name);

    return (
        <div className="flex h-full items-center gap-1.5 overflow-hidden">
            <span className="truncate text-xs font-bold text-astara-purple">
                {resolved.text}
            </span>
            {resolved.fellBack && (
                <LocaleFallbackChip requested={locale} used={resolved.locale} />
            )}
        </div>
    );
};

const KeyCell = ({ data }: CustomCellRendererProps<CatalogModel>) => (
    <div className="flex h-full items-center font-mono text-[11px] text-gray-500">
        {data?.model_key}
    </div>
);

const YearsCell = ({ data }: CustomCellRendererProps<CatalogModel>) => (
    <div className="flex h-full items-center justify-end text-[11px] font-semibold text-gray-600 tabular-nums">
        {data?.model_years_count ?? 0}
    </div>
);

const CountCell = ({ value }: { value: number }) => (
    <div className="flex h-full items-center justify-end text-[11px] font-semibold text-gray-600 tabular-nums">
        {value}
    </div>
);

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

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

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

        return [
            {
                colId: 'brand',
                headerName: 'Brand',
                field: 'brand.code',
                width: 120,
                sortable: true,
                sort: sort?.colId === 'brand' ? sort.sort : undefined,
                cellRenderer: BrandCell,
            },
            {
                colId: 'name',
                headerName: 'Model',
                field: 'name',
                flex: 2,
                minWidth: 240,
                sortable: true,
                sort: sort?.colId === 'name' ? sort.sort : undefined,
                cellRenderer: NameCell,
            },
            {
                colId: 'model_key',
                headerName: 'Key',
                field: 'model_key',
                width: 150,
                cellRenderer: KeyCell,
            },
            {
                colId: 'years',
                headerName: 'Years',
                field: 'model_years_count',
                width: 80,
                cellRenderer: YearsCell,
            },
            {
                colId: 'body_types',
                headerName: 'Body types',
                field: 'body_types_count',
                width: 100,
                cellRenderer: (
                    params: CustomCellRendererProps<CatalogModel>,
                ) => <CountCell value={params.data?.body_types_count ?? 0} />,
            },
            {
                colId: 'variants',
                headerName: 'Variants',
                field: 'variants_count',
                width: 90,
                cellRenderer: (
                    params: CustomCellRendererProps<CatalogModel>,
                ) => <CountCell value={params.data?.variants_count ?? 0} />,
            },
            {
                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<CatalogModel>) => {
        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?: CatalogModel;
    }) => {
        if (!event.data) {
            return;
        }

        router.visit(modelShow({ model: event.data.id }));
    };

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

    return (
        <div className="flex flex-1 flex-col overflow-hidden">
            <PageHeader title="Models" subtitle="Vehicle catalog — models">
                {markets.length > 0 && (
                    <span className="inline-flex h-[22px] items-center rounded bg-slate-100 px-2.5 text-[10px] font-bold tracking-widest text-slate-600 uppercase">
                        Market: {markets[0]}
                    </span>
                )}
            </PageHeader>

            <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 name or key..."
                            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>
                    <BrandTags
                        brands={brands}
                        active={filters.brand}
                        onSelect={(brand) => updateQuery({ ...filters, brand })}
                    />
                    <StatusSelect
                        statuses={statuses}
                        active={filters.status}
                        onSelect={(status) =>
                            updateQuery({ ...filters, status })
                        }
                    />
                </div>

                {models.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 models match the current filters"
                            description="Adjust the search, brand 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<CatalogModel>
                                theme={astaraGridTheme}
                                rowData={models.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={models.links} meta={models.meta} />
                    </div>
                )}
            </div>
        </div>
    );
}
