"use client";

import * as React from "react";
import { useState, useMemo } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ChevronRight, ChevronDown, Folder, Layers, Network, Search, Plus } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import { CategoryDiagram } from "./CategoryDiagram";
import { CategoryDialogs } from "@/components/dashboard/categorypage/CategoryDialogs";
import { CategoryActionMenu } from "@/components/dashboard/categorypage/CategoryActionMenu";

interface Category {
  id: string;
  name: string;
  parent_id: string | null;
}

interface TreeNode extends Category {
  children: TreeNode[];
}

interface CategoryVisualizerProps {
  categories: Category[];
}

const CategoryVisualizerInner = ({ categories }: CategoryVisualizerProps) => {
  const [activeTab, setActiveTab] = useState("hierarchical");
  const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());
  const [searchQuery, setSearchQuery] = useState("");
  const [debouncedSearchQuery, setDebouncedSearchQuery] = useState("");

  // CRUD State
  const [isAddOpen, setIsAddOpen] = useState(false);
  const [parentIdForAdd, setParentIdForAdd] = useState<string | null>(null);
  const [parentNameForAdd, setParentNameForAdd] = useState<string | null>(null);

  const [isEditOpen, setIsEditOpen] = useState(false);
  const [categoryToEdit, setCategoryToEdit] = useState<{ id: string; name: string; parent_id: string | null } | null>(null);

  const [isDeleteOpen, setIsDeleteOpen] = useState(false);
  const [categoryToDelete, setCategoryToDelete] = useState<{ id: string; name: string } | null>(null);

  /*
    ⚡ Optimization: Debounced Search
    Prevents expensive re-renders and recursive search logic on every keystroke.
  */
  React.useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedSearchQuery(searchQuery);
    }, 250);
    return () => clearTimeout(timer);
  }, [searchQuery]);

  const treeData = useMemo(() => {
    const map = new Map<string | null, TreeNode[]>();
    categories.forEach((cat) => {
      const parentId = cat.parent_id;
      if (!map.has(parentId)) map.set(parentId, []);
      map.get(parentId)!.push({ ...cat, children: [] });
    });

    const buildTree = (parentId: string | null): TreeNode[] => {
      const nodes = map.get(parentId) || [];
      nodes.forEach((node) => {
        node.children = buildTree(node.id);
      });
      return nodes;
    };

    return buildTree(null);
  }, [categories]);

  const toggleNode = (id: string) => {
    const next = new Set(expandedNodes);
    if (next.has(id)) next.delete(id);
    else next.add(id);
    setExpandedNodes(next);
  };

  // Handlers
  const handleAddChild = React.useCallback((parentId: string | null, parentName: string | null) => {
    setParentIdForAdd(parentId);
    setParentNameForAdd(parentName);
    setIsAddOpen(true);
  }, []);

  const handleEdit = React.useCallback((id: string, name: string) => {
    // We need to find the category from the prop, which is captured in closure if not in deps.
    // However, categories prop changes when data updates.
    // Better to pass just ID and let the dialog find it or set it here.
    // We can't access 'categories' inside useCallback unless we add it to deps.
    // But adding categories to deps will cause re-creation on every refresh.
    // Let's rely on the fact that we set state here.
    // Actually, we need the category object.
    // Let's pass the full category object if possible, or just ID and Name.
    // The dialogs use 'categoryToEdit' which has parent_id.
    // We need to find it.
    // Let's use functional update or ref if performance is critical, but here simple find is fine.
    // We will add categories to deps.
    const cat = categories.find(c => c.id === id);
    if (cat) {
      setCategoryToEdit(cat);
      setIsEditOpen(true);
    }
  }, [categories]);

  const handleDelete = React.useCallback((id: string, name: string) => {
    setCategoryToDelete({ id, name });
    setIsDeleteOpen(true);
  }, []);

  /*
    ⚡ Optimization: Pre-calculated Search Matches
    Instead of recursive O(N^2) search during render, we pre-calculate visibility
    in a single O(N) pass when the query or data changes.
  */
  const { matchingNodeIds, nodesWithMatchingChildren } = useMemo(() => {
    const matches = new Set<string>();
    const withMatchingChildren = new Set<string>();

    if (!debouncedSearchQuery) return { matchingNodeIds: matches, nodesWithMatchingChildren: withMatchingChildren };

    const query = debouncedSearchQuery.toLowerCase();

    const checkNode = (node: TreeNode): boolean => {
      const isMatch = node.name.toLowerCase().includes(query);
      if (isMatch) matches.add(node.id);

      let hasMatchInDescendants = false;
      for (const child of node.children) {
        if (checkNode(child)) {
          hasMatchInDescendants = true;
        }
      }

      if (hasMatchInDescendants) withMatchingChildren.add(node.id);
      return isMatch || hasMatchInDescendants;
    };

    treeData.forEach(node => checkNode(node));

    return { matchingNodeIds: matches, nodesWithMatchingChildren: withMatchingChildren };
  }, [treeData, debouncedSearchQuery]);

  const renderTree = (nodes: TreeNode[], level = 0) => {
    return (
      <div className={cn("space-y-1", level > 0 && "ml-6 pl-4 border-l border-border-light dark:border-border-dark")}>
        {nodes.map((node) => {
          const isMatch = matchingNodeIds.has(node.id);
          const hasMatchInDescendants = nodesWithMatchingChildren.has(node.id);
          
          if (debouncedSearchQuery && !isMatch && !hasMatchInDescendants) return null;

          return (
            <div key={node.id}>
              <div className="flex items-center group justify-between pr-4 hover:bg-muted/30 rounded-md">
                <div className="flex items-center">
                  {node.children.length > 0 ? (
                    <button
                      onClick={() => toggleNode(node.id)}
                      className="p-1 hover:bg-muted rounded text-muted-foreground mr-1"
                    >
                      {expandedNodes.has(node.id) || searchQuery ? (
                        <ChevronDown className="h-4 w-4" />
                      ) : (
                        <ChevronRight className="h-4 w-4" />
                      )}
                    </button>
                  ) : (
                    <div className="w-6 h-4 mr-1" />
                  )}
                  <div className={cn(
                    "flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors",
                    isMatch ? "text-primary font-bold" : 
                    node.children.length > 0 ? "font-semibold text-foreground" : "text-muted-foreground"
                  )}>
                    <Folder className={cn("h-4 w-4", node.children.length > 0 ? "text-primary" : "text-muted-foreground")} />
                    {node.name}
                  </div>
                </div>

                <div className="opacity-0 group-hover:opacity-100 transition-opacity">
                    <CategoryActionMenu 
                        categoryId={node.id} 
                        categoryName={node.name}
                        onAddChild={handleAddChild}
                        onEdit={handleEdit}
                        onDelete={handleDelete}
                    />
                </div>
              </div>
              {(expandedNodes.has(node.id) || debouncedSearchQuery) && node.children.length > 0 && renderTree(node.children, level + 1)}
            </div>
          );
        })}
      </div>
    );
  };

  return (
    <>
      <Card className="border-border-light dark:border-border-dark shadow-sm overflow-hidden">
        <CardHeader className="border-b bg-muted/30">
          <div className="flex items-center justify-between">
            <CardTitle className="text-lg font-medium flex items-center gap-2">
              <Network className="h-5 w-5 text-primary" />
              Kategorien Struktur
            </CardTitle>
            <div className="flex items-center gap-4">
              <Button 
                size="sm" 
                variant="outline" 
                className="h-9 gap-2"
                onClick={() => handleAddChild(null, "Root")}
              >
                <Plus className="h-4 w-4" />
                Root Kategorie
              </Button>
              <div className="relative w-64">
                  <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
                  <Input
                      placeholder="Suchen..."
                      value={searchQuery}
                      onChange={(e) => setSearchQuery(e.target.value)}
                      className="pl-9 h-9"
                  />
              </div>
              <Tabs value={activeTab} onValueChange={setActiveTab}>
                  <TabsList className="grid w-[350px] grid-cols-2">
                  <TabsTrigger value="hierarchical" className="gap-2">
                      <Layers className="h-4 w-4" />
                      Baum-Ansicht
                  </TabsTrigger>
                  <TabsTrigger value="diagram" className="gap-2">
                      <Network className="h-4 w-4" />
                      Struktur-Diagramm
                  </TabsTrigger>
                  </TabsList>
              </Tabs>
            </div>
          </div>
        </CardHeader>
        <CardContent className="p-0">
          <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
              <TabsContent value="hierarchical" className="p-6 m-0">
                  <div className="max-h-[600px] overflow-auto custom-scrollbar">
                      {renderTree(treeData)}
                  </div>
              </TabsContent>
              <TabsContent value="diagram" className="p-0 m-0">
                  <CategoryDiagram 
                    categories={categories} 
                    onAddChild={handleAddChild}
                    onEdit={handleEdit}
                    onDelete={handleDelete}
                  />
              </TabsContent>
          </Tabs>
        </CardContent>
      </Card>

      <CategoryDialogs
        isAddOpen={isAddOpen}
        onAddOpenChange={setIsAddOpen}
        parentIdForAdd={parentIdForAdd}
        parentNameForAdd={parentNameForAdd}
        isEditOpen={isEditOpen}
        onEditOpenChange={setIsEditOpen}
        categoryToEdit={categoryToEdit}
        isDeleteOpen={isDeleteOpen}
        onDeleteOpenChange={setIsDeleteOpen}
        categoryToDelete={categoryToDelete}
        categories={categories}
      />
    </>
  );
};

CategoryVisualizerInner.displayName = "CategoryVisualizer";

/**
 * ⚡ Optimization: Memoized CategoryVisualizer
 * Prevents unnecessary re-renders when parent components update.
 */
export const CategoryVisualizer = React.memo(CategoryVisualizerInner);
