"use client";

import React, { useMemo, useState, useCallback } from "react";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";

export type CategoryOption = {
    id: string;
    name: string;
    slug?: string;
    parentId: string | null;
    sortOrder?: number;
};

type Props = {
    categories: CategoryOption[];
    value: string[]; // selected categoryIds
    onChange: (next: string[]) => void;
};

type TreeIndex = {
    byParent: Map<string | null, CategoryOption[]>;
    byId: Map<string, CategoryOption>;
    parentOf: Map<string, string | null>;
};

function buildIndex(items: CategoryOption[]): TreeIndex {
    const safeItems = Array.isArray(items) ? items : [];

    const byParent = new Map<string | null, CategoryOption[]>();
    const byId = new Map<string, CategoryOption>();
    const parentOf = new Map<string, string | null>();

    for (const c of safeItems) {
        byId.set(c.id, c);
        parentOf.set(c.id, c.parentId ?? null);
        const k = c.parentId ?? null;
        byParent.set(k, [...(byParent.get(k) ?? []), c]);
    }

    // مرتب‌سازی: sortOrder سپس name
    for (const [k, arr] of byParent.entries()) {
        arr.sort((a, b) => {
            const sa = a.sortOrder ?? 0;
            const sb = b.sortOrder ?? 0;
            if (sa !== sb) return sa - sb;
            return a.name.localeCompare(b.name, "fa");
        });
        byParent.set(k, arr);
    }

    return { byParent, byId, parentOf };
}

function uniq(ids: string[]) {
    return Array.from(new Set(ids));
}

export function CategoryPicker({ categories, value, onChange }: Props) {
    const [query, setQuery] = useState("");
    const selectedSet = useMemo(() => new Set(value), [value]);

    const index = useMemo(() => buildIndex(categories ?? []), [categories]);
    const roots = useMemo(() => index.byParent.get(null) ?? [], [index]);

    // expanded: اگر خالی باشد یعنی همه باز باشند (برای UX بهتر)
    const [collapsed, setCollapsed] = useState<Set<string>>(new Set());

    const isCollapsed = useCallback(
        (id: string) => collapsed.has(id),
        [collapsed]
    );

    const toggleCollapse = useCallback((id: string) => {
        setCollapsed((prev) => {
            const next = new Set(prev);
            if (next.has(id)) next.delete(id);
            else next.add(id);
            return next;
        });
    }, []);

    const expandAll = useCallback(() => setCollapsed(new Set()), []);
    const collapseAll = useCallback(() => {
        // همه‌ی نودهایی که child دارند را collapse کن
        const next = new Set<string>();
        for (const [parentId, children] of index.byParent.entries()) {
            if (parentId && children?.length) next.add(parentId);
        }
        setCollapsed(next);
    }, [index]);

    const toggle = useCallback(
        (id: string, checked: boolean) => {
            if (checked) onChange(uniq([...value, id]));
            else onChange(value.filter((x) => x !== id));
        },
        [onChange, value]
    );

    const clear = useCallback(() => onChange([]), [onChange]);

    const selected = useMemo(() => {
        const out: CategoryOption[] = [];
        for (const id of value) {
            const c = index.byId.get(id);
            if (c) out.push(c);
        }
        return out;
    }, [value, index]);

    // ---------- Search filtering (show matching + ancestors) ----------
    const normalizedQuery = query.trim().toLowerCase();

    const visibleSet = useMemo(() => {
        if (!normalizedQuery) return null; // یعنی همه قابل نمایش

        const keep = new Set<string>();
        const q = normalizedQuery;

        // هر نودی که match شود + کل والدهای مسیر
        for (const c of categories ?? []) {
            const name = (c.name ?? "").toLowerCase();
            const slug = (c.slug ?? "").toLowerCase();

            if (name.includes(q) || slug.includes(q)) {
                keep.add(c.id);

                // ancestors
                let cur: string | null = c.parentId ?? null;
                while (cur) {
                    keep.add(cur);
                    cur = index.parentOf.get(cur) ?? null;
                }
            }
        }

        return keep;
    }, [normalizedQuery, categories, index]);

    const renderNode = (node: CategoryOption, depth: number) => {
        if (visibleSet && !visibleSet.has(node.id)) return null;

        const children = index.byParent.get(node.id) ?? [];
        const checked = selectedSet.has(node.id);
        const hasChildren = children.length > 0;
        const collapsedNow = hasChildren ? isCollapsed(node.id) : false;

        return (
            <div key={node.id} className="space-y-1">
                <div
                    className="flex items-center gap-2 rounded-md px-2 py-1 hover:bg-muted/50"
                    style={{ paddingInlineStart: depth * 14 }}
                >
                    {hasChildren ? (
                        <button
                            type="button"
                            onClick={() => toggleCollapse(node.id)}
                            className="h-6 w-6 shrink-0 rounded hover:bg-muted flex items-center justify-center text-xs"
                            aria-label={collapsedNow ? "باز کردن" : "بستن"}
                        >
                            {collapsedNow ? "◀" : "▼"}
                        </button>
                    ) : (
                        <span className="h-6 w-6 shrink-0" />
                    )}

                    <Checkbox
                        checked={checked}
                        onCheckedChange={(c) => toggle(node.id, !!c)}
                        id={`cat-${node.id}`}
                    />

                    <label
                        htmlFor={`cat-${node.id}`}
                        className="cursor-pointer text-sm leading-6"
                    >
                        {node.name}
                    </label>

                    {node.slug ? (
                        <span className="ms-auto text-xs text-muted-foreground hidden sm:inline">
                            {node.slug}
                        </span>
                    ) : null}
                </div>

                {hasChildren && !collapsedNow && (
                    <div className="space-y-1">
                        {children.map((ch) => renderNode(ch, depth + 1))}
                    </div>
                )}
            </div>
        );
    };

    return (
        <div className="space-y-3">
            {/* Selected chips */}
            <div className="flex flex-wrap gap-1">
                {selected.length === 0 ? (
                    <div className="text-xs text-muted-foreground">
                        هیچ دسته‌ای انتخاب نشده است.
                    </div>
                ) : (
                    selected.map((c) => (
                        <Badge
                            key={c.id}
                            variant="secondary"
                            className="cursor-pointer"
                            onClick={() => toggle(c.id, false)}
                            title="حذف"
                        >
                            {c.name}
                        </Badge>
                    ))
                )}
            </div>

            {/* Search + actions */}
            <div className="flex flex-col gap-2 md:flex-row md:items-center">
                <Input
                    value={query}
                    onChange={(e) => setQuery(e.target.value)}
                    placeholder="جستجو در دسته‌ها..."
                />

                <div className="flex gap-2">
                    <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        onClick={() => {
                            window.dispatchEvent(
                                new CustomEvent("open-category-create")
                            );
                        }}
                    >
                        + جدید
                    </Button>
                    <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        onClick={expandAll}
                    >
                        باز کردن همه
                    </Button>
                    <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        onClick={collapseAll}
                    >
                        بستن همه
                    </Button>
                    <Button
                        type="button"
                        size="sm"
                        variant="ghost"
                        onClick={clear}
                        disabled={value.length === 0}
                    >
                        پاک کردن
                    </Button>
                </div>
            </div>

            {/* Tree */}
            <div className="max-h-[420px] overflow-auto rounded-md border p-2">
                <div className="space-y-1">
                    {roots.length === 0 ? (
                        <div className="p-3 text-xs text-muted-foreground">
                            هیچ دسته فعالی یافت نشد.
                        </div>
                    ) : (
                        roots.map((r) => renderNode(r, 0))
                    )}
                </div>
            </div>

            <div className="text-xs text-muted-foreground">
                نکته: می‌توانید چند دسته را همزمان انتخاب کنید. حذف با کلیک روی
                چیپ‌ها انجام می‌شود.
            </div>
        </div>
    );
}
