import React, { useEffect, useState } from "react";
import { Check, Search } from "lucide-react";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "./dialog";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "./accordion";
import { Input } from "./input";
import { Switch } from "./switch";
import { Button } from "./button";
import { cn } from "@/lib/utils";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface CategoryChild {
  id: string;
  name: string;
  icon?: React.ReactNode;
}

export interface CategoryItem {
  id: string;
  name: string;
  icon?: React.ReactNode;
  subCategories?: CategoryChild[];
}

export interface CategoryEditDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** Transaction description shown as subtitle in the dialog header */
  transactionDescription?: string;
  /** Currently assigned category ID — pre-selects and auto-expands the matching parent */
  currentCategoryId?: string;
  /** Full category tree to display */
  categories: CategoryItem[];
  /** Called on Save — receives the chosen category ID and the "apply to future" toggle state */
  onSave: (categoryId: string, applyToFuture: boolean) => void;
}

// ---------------------------------------------------------------------------
// Internal sub-components
// ---------------------------------------------------------------------------

function ItemIcon({
  icon,
  active,
}: {
  icon?: React.ReactNode;
  active: boolean;
}) {
  if (!icon) return null;
  return (
    <span
      className={cn(
        "shrink-0",
        active ? "text-primary" : "text-muted-foreground",
      )}
    >
      {icon}
    </span>
  );
}

function CategoryRow({
  name,
  icon,
  isSelected,
  indent = false,
  onClick,
}: {
  name: string;
  icon?: React.ReactNode;
  isSelected: boolean;
  indent?: boolean;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        "flex w-full items-center gap-2 text-left text-body-small transition-colors hover:bg-muted",
        indent ? "py-2 pl-9 pr-4" : "px-4 py-2.5",
        isSelected && "bg-primary/10",
      )}
    >
      <ItemIcon icon={icon} active={false} />
      <span className="flex-1">{name}</span>
      {isSelected && <Check className="size-3.5 shrink-0 text-primary" />}
    </button>
  );
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export function CategoryEditDialog({
  open,
  onOpenChange,
  transactionDescription,
  currentCategoryId,
  categories,
  onSave,
}: CategoryEditDialogProps) {
  const [search, setSearch] = useState("");
  const [selected, setSelected] = useState(currentCategoryId ?? "");
  const [applyToFuture, setApplyToFuture] = useState(false);
  const [openItem, setOpenItem] = useState<string>("");

  useEffect(() => {
    if (!open) return;
    setSelected(currentCategoryId ?? "");
    setSearch("");
    setApplyToFuture(false);
    const parent = categories.find(
      (c) =>
        c.id === currentCategoryId ||
        c.subCategories?.some((s) => s.id === currentCategoryId),
    );
    setOpenItem(parent?.id ?? "");
  }, [open, currentCategoryId, categories]);

  const q = search.toLowerCase();

  const filtered = categories.filter(
    (c) =>
      !q ||
      c.name.toLowerCase().includes(q) ||
      c.subCategories?.some((s) => s.name.toLowerCase().includes(q)),
  );

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent size="sm" className="gap-0 p-0">
        <DialogHeader className="px-5 pt-5 pb-3">
          <DialogTitle>Change Category</DialogTitle>
          {transactionDescription && (
            <p className="truncate text-caption text-muted-foreground">
              {transactionDescription}
            </p>
          )}
        </DialogHeader>

        {/* Search */}
        <div className="px-4 pb-3">
          <div className="relative">
            <Search className="absolute left-3 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
            <Input
              placeholder="Search categories…"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              className="h-8 pl-8 text-body-small"
            />
          </div>
        </div>

        {/* Category list */}
        <div className="max-h-64 overflow-y-auto border-y border-border">
          {filtered.length === 0 ? (
            <p className="py-8 text-center text-caption text-muted-foreground">
              No categories found
            </p>
          ) : q ? (
            // Search mode — flat list, no animation
            filtered.map((cat) => {
              const hasChildren = (cat.subCategories?.length ?? 0) > 0;
              const matchingChildren = cat.subCategories?.filter((s) =>
                s.name.toLowerCase().includes(q),
              );

              return (
                <div key={cat.id}>
                  {(!hasChildren || cat.name.toLowerCase().includes(q)) &&
                    (hasChildren ? (
                      // Non-selectable group header
                      <div className="flex items-center gap-2 px-4 py-2.5 text-body-small">
                        <ItemIcon icon={cat.icon} active={false} />
                        <span className="flex-1 text-muted-foreground">
                          {cat.name}
                        </span>
                      </div>
                    ) : (
                      <CategoryRow
                        name={cat.name}
                        icon={cat.icon}
                        isSelected={selected === cat.id}
                        onClick={() => setSelected(cat.id)}
                      />
                    ))}
                  {matchingChildren?.map((sub) => (
                    <CategoryRow
                      key={sub.id}
                      name={sub.name}
                      icon={sub.icon}
                      isSelected={selected === sub.id}
                      indent
                      onClick={() => setSelected(sub.id)}
                    />
                  ))}
                </div>
              );
            })
          ) : (
            // Browse mode — accordion with animated expand/collapse
            <Accordion
              value={openItem ? [openItem] : []}
              onValueChange={(v) => setOpenItem(v[0] ?? "")}
            >
              {filtered.map((cat) => {
                if ((cat.subCategories?.length ?? 0) > 0) {
                  return (
                    <AccordionItem
                      key={cat.id}
                      value={cat.id}
                      className="border-b border-border last:border-0"
                    >
                      <AccordionTrigger className="gap-2 px-4 py-2.5 text-body-small hover:bg-muted hover:no-underline [&>svg:last-child]:size-3.5 [&>svg:last-child]:text-muted-foreground">
                        <ItemIcon icon={cat.icon} active={false} />
                        <span className="flex-1 text-left">{cat.name}</span>
                      </AccordionTrigger>
                      <AccordionContent className="p-0 text-current">
                        {cat.subCategories!.map((sub) => (
                          <CategoryRow
                            key={sub.id}
                            name={sub.name}
                            icon={sub.icon}
                            isSelected={selected === sub.id}
                            indent
                            onClick={() => setSelected(sub.id)}
                          />
                        ))}
                      </AccordionContent>
                    </AccordionItem>
                  );
                }

                return (
                  <div
                    key={cat.id}
                    className="border-b border-border last:border-0"
                  >
                    <CategoryRow
                      name={cat.name}
                      icon={cat.icon}
                      isSelected={selected === cat.id}
                      onClick={() => setSelected(cat.id)}
                    />
                  </div>
                );
              })}
            </Accordion>
          )}
        </div>

        {/* Apply to future toggle */}
        <div className="flex items-center justify-between gap-3 px-4 py-3">
          <label className="text-caption text-muted-foreground">
            Apply to all future transactions from this merchant
          </label>
          <Switch
            checked={applyToFuture}
            onCheckedChange={setApplyToFuture}
            className="shrink-0"
          />
        </div>

        {/* Actions */}
        <div className="flex gap-2 px-4 pb-4">
          <Button
            variant="outline"
            size="sm"
            className="flex-1"
            onClick={() => onOpenChange(false)}
          >
            Cancel
          </Button>
          <Button
            size="sm"
            className="flex-1"
            disabled={!selected || selected === currentCategoryId}
            onClick={() => {
              onSave(selected, applyToFuture);
              onOpenChange(false);
            }}
          >
            Save
          </Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}
