"use client";

import { useState, useMemo } from "react";
import { PageLayout, LoadingState, PageHeader } from "@/components/layout";
import {
  CategoryCard,
  CategoryEditDialog,
  ParentCategoryRow,
  CategorySearchBar,
} from "@/components/categories";
import { useBankingData } from "@/lib/hooks";
import { Button } from "@/components/ui/button";
import { Plus } from "lucide-react";
import {
  autoCategorize,
  addCategory,
  updateCategory,
  deleteCategory,
} from "@/lib/store-db";
import type { Category } from "@/lib/types";

export default function CategoriesPage() {
  const { data, isLoading, refresh } = useBankingData();
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [editingCategory, setEditingCategory] = useState<Category | null>(null);
  const [expandedParents, setExpandedParents] = useState<Set<string>>(
    new Set()
  );
  const [formData, setFormData] = useState({
    name: "",
    color: "#22c55e",
    icon: "tag",
    keywords: [] as string[],
    parentId: null as string | null,
  });
  const [searchQuery, setSearchQuery] = useState("");

  // Organiser les catégories par parent
  const { parentCategories, childrenByParent, orphanCategories } =
    useMemo(() => {
      if (!data?.categories)
        return {
          parentCategories: [],
          childrenByParent: {},
          orphanCategories: [],
        };

      const parents = data.categories.filter((c) => c.parentId === null);
      const children: Record<string, Category[]> = {};
      const orphans: Category[] = [];

      data.categories
        .filter((c) => c.parentId !== null)
        .forEach((child) => {
          const parentExists = parents.some((p) => p.id === child.parentId);
          if (parentExists) {
            if (!children[child.parentId!]) {
              children[child.parentId!] = [];
            }
            children[child.parentId!].push(child);
          } else {
            orphans.push(child);
          }
        });

      return {
        parentCategories: parents,
        childrenByParent: children,
        orphanCategories: orphans,
      };
    }, [data?.categories]);

  // Initialiser tous les parents comme ouverts
  useState(() => {
    if (parentCategories.length > 0 && expandedParents.size === 0) {
      setExpandedParents(new Set(parentCategories.map((p) => p.id)));
    }
  });

  if (isLoading || !data) {
    return <LoadingState />;
  }

  const formatCurrency = (amount: number) => {
    return new Intl.NumberFormat("fr-FR", {
      style: "currency",
      currency: "EUR",
    }).format(amount);
  };

  const getCategoryStats = (categoryId: string, includeChildren = false) => {
    let categoryIds = [categoryId];

    if (includeChildren && childrenByParent[categoryId]) {
      categoryIds = [
        ...categoryIds,
        ...childrenByParent[categoryId].map((c) => c.id),
      ];
    }

    const categoryTransactions = data.transactions.filter((t) =>
      categoryIds.includes(t.categoryId || "")
    );
    const total = categoryTransactions.reduce(
      (sum, t) => sum + Math.abs(t.amount),
      0
    );
    const count = categoryTransactions.length;
    return { total, count };
  };

  const toggleExpanded = (parentId: string) => {
    const newExpanded = new Set(expandedParents);
    if (newExpanded.has(parentId)) {
      newExpanded.delete(parentId);
    } else {
      newExpanded.add(parentId);
    }
    setExpandedParents(newExpanded);
  };

  const expandAll = () => {
    setExpandedParents(new Set(parentCategories.map((p) => p.id)));
  };

  const collapseAll = () => {
    setExpandedParents(new Set());
  };

  const allExpanded =
    parentCategories.length > 0 &&
    expandedParents.size === parentCategories.length;

  const handleNewCategory = (parentId: string | null = null) => {
    setEditingCategory(null);
    setFormData({ name: "", color: "#22c55e", icon: "tag", keywords: [], parentId });
    setIsDialogOpen(true);
  };

  const handleEdit = (category: Category) => {
    setEditingCategory(category);
    setFormData({
      name: category.name,
      color: category.color,
      icon: category.icon,
      keywords: [...category.keywords],
      parentId: category.parentId,
    });
    setIsDialogOpen(true);
  };

  const handleSave = async () => {
    try {
      if (editingCategory) {
        await updateCategory({
          ...editingCategory,
          name: formData.name,
          color: formData.color,
          icon: formData.icon,
          keywords: formData.keywords,
          parentId: formData.parentId,
        });
      } else {
        await addCategory({
          name: formData.name,
          color: formData.color,
          icon: formData.icon,
          keywords: formData.keywords,
          parentId: formData.parentId,
        });
      }
      refresh();
      setIsDialogOpen(false);
    } catch (error) {
      console.error("Error saving category:", error);
      alert("Erreur lors de la sauvegarde de la catégorie");
    }
  };

  const handleDelete = async (categoryId: string) => {
    const hasChildren = childrenByParent[categoryId]?.length > 0;
    const message = hasChildren
      ? "Cette catégorie a des sous-catégories. Supprimer quand même ?"
      : "Supprimer cette catégorie ?";

    if (!confirm(message)) return;

    try {
      await deleteCategory(categoryId);
      refresh();
    } catch (error) {
      console.error("Error deleting category:", error);
      alert("Erreur lors de la suppression de la catégorie");
    }
  };

  const reApplyAutoCategories = async () => {
    if (
      !confirm(
        "Recatégoriser automatiquement les transactions non catégorisées ?"
      )
    )
      return;

    try {
      const { updateTransaction } = await import("@/lib/store-db");
      const uncategorized = data.transactions.filter((t) => !t.categoryId);

      for (const transaction of uncategorized) {
        const categoryId = autoCategorize(
          transaction.description + " " + (transaction.memo || ""),
          data.categories
        );
        if (categoryId) {
          await updateTransaction({ ...transaction, categoryId });
        }
      }
      refresh();
    } catch (error) {
      console.error("Error re-categorizing:", error);
      alert("Erreur lors de la recatégorisation");
    }
  };

  const uncategorizedCount = data.transactions.filter(
    (t) => !t.categoryId
  ).length;

  // Filtrer les catégories selon la recherche
  const filteredParentCategories = parentCategories.filter((parent) => {
    if (!searchQuery.trim()) return true;
    const query = searchQuery.toLowerCase();
    if (parent.name.toLowerCase().includes(query)) return true;
    if (parent.keywords.some((k) => k.toLowerCase().includes(query)))
      return true;
    const children = childrenByParent[parent.id] || [];
    return children.some(
      (c) =>
        c.name.toLowerCase().includes(query) ||
        c.keywords.some((k) => k.toLowerCase().includes(query))
    );
  });

  return (
    <PageLayout>
      <PageHeader
        title="Catégories"
        description={`${parentCategories.length} catégories principales • ${data.categories.length - parentCategories.length} sous-catégories`}
        actions={
          <>
            {uncategorizedCount > 0 && (
              <Button variant="outline" onClick={reApplyAutoCategories}>
                Recatégoriser ({uncategorizedCount})
              </Button>
            )}
            <Button onClick={() => handleNewCategory(null)}>
              <Plus className="w-4 h-4 mr-2" />
              Nouvelle catégorie
            </Button>
          </>
        }
      />

      <CategorySearchBar
        searchQuery={searchQuery}
        onSearchChange={setSearchQuery}
        allExpanded={allExpanded}
        onToggleAll={allExpanded ? collapseAll : expandAll}
      />

      <div className="space-y-1">
        {filteredParentCategories.map((parent) => {
          const allChildren = childrenByParent[parent.id] || [];
          const children = searchQuery.trim()
            ? allChildren.filter(
                (c) =>
                  c.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
                  c.keywords.some((k) =>
                    k.toLowerCase().includes(searchQuery.toLowerCase())
                  ) ||
                  parent.name.toLowerCase().includes(searchQuery.toLowerCase())
              )
            : allChildren;
          const stats = getCategoryStats(parent.id, true);
          const isExpanded =
            expandedParents.has(parent.id) ||
            (searchQuery.trim() !== "" && children.length > 0);

          return (
            <ParentCategoryRow
              key={parent.id}
              parent={parent}
              children={children}
              stats={stats}
              isExpanded={isExpanded}
              onToggleExpanded={() => toggleExpanded(parent.id)}
              formatCurrency={formatCurrency}
              getCategoryStats={(id) => getCategoryStats(id)}
              onEdit={handleEdit}
              onDelete={handleDelete}
              onNewCategory={handleNewCategory}
            />
          );
        })}

        {orphanCategories.length > 0 && (
          <div className="border rounded-lg bg-card">
            <div className="px-3 py-2 border-b">
              <span className="text-sm font-medium text-muted-foreground">
                Catégories non classées ({orphanCategories.length})
              </span>
            </div>
            <div className="p-2 space-y-1">
              {orphanCategories.map((category) => (
                <CategoryCard
                  key={category.id}
                  category={category}
                  stats={getCategoryStats(category.id)}
                  formatCurrency={formatCurrency}
                  onEdit={handleEdit}
                  onDelete={handleDelete}
                />
              ))}
            </div>
          </div>
        )}
      </div>

      <CategoryEditDialog
        open={isDialogOpen}
        onOpenChange={setIsDialogOpen}
        editingCategory={editingCategory}
        formData={formData}
        onFormDataChange={setFormData}
        parentCategories={parentCategories}
        onSave={handleSave}
      />
    </PageLayout>
  );
}
