"use client";

import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { useClickOutside } from "@/hooks/useClickOutside";
import { useAppDispatch, useAppSelector } from "@/state/hooks";
import {
  fetchCategoryTree,
  createCategory,
  updateCategory,
  changeCategoryStatus,
  deleteCategory,
} from "@/state/category/categorySlice";
import type { CategoryNode, CreateCategoryPayload, UpdateCategoryPayload } from "@/types/category";
import { getImageUrl } from "@/lib/imageUrl";
import ToggleSwitch from "../common/ToggleSwitch";
import {
  CategoriesIcon,
  EyeViewIcon,
  KebabIcon,
  PencilIcon,
  PlusCircleIcon,
  PowerIcon,
  TagIcon,
  TrashIcon,
  TriangleDisclosureIcon,
} from "../dashboard/icons";
import AddCategoryModal, { type EditTarget } from "./AddCategoryModal";
import CategoryProductsDrawer from "./CategoryProductsDrawer";
import CategoryStatusModal from "./CategoryStatusModal";
import RemoveCategoryModal from "./RemoveCategoryModal";

function formatDate(dateStr?: string | Date): string {
  if (!dateStr) return "-";
  try {
    const d = new Date(dateStr);
    if (isNaN(d.getTime())) return String(dateStr);
    return d.toISOString().split("T")[0];
  } catch {
    return String(dateStr);
  }
}

export default function CategoryManagementTable() {
  const dispatch = useAppDispatch();
  const { tree, loading, actionLoading } = useAppSelector((state) => state.category);

  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  const [openMenu, setOpenMenu] = useState<string | null>(null);
  const [formState, setFormState] = useState<{ mode: "add" } | { mode: "edit"; target: EditTarget } | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<{ id: string; name: string } | null>(null);
  const [productsDrawerTarget, setProductsDrawerTarget] = useState<{
    id: string;
    name: string;
    navigationName: string;
  } | null>(null);
  const [statusConfirm, setStatusConfirm] = useState<{
    id: string;
    name: string;
    action: "inactivate" | "activate";
  } | null>(null);

  // Fetch tree on mount
  useEffect(() => {
    dispatch(fetchCategoryTree(undefined));
  }, [dispatch]);

  // Auto-expand root and navigation nodes on first load
  useEffect(() => {
    if (tree.length > 0) {
      setExpanded((prev) => {
        if (prev.size > 0) return prev;
        const next = new Set<string>();
        tree.forEach((root) => {
          next.add(root.id);
          const navChildren = root.children || root.subCategories || [];
          navChildren.forEach((nav) => next.add(nav.id));
        });
        return next;
      });
    }
  }, [tree]);

  const toggleExpand = (id: string) => {
    setExpanded((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const handleCreate = async (payload: CreateCategoryPayload | FormData) => {
    try {
      const res = await dispatch(createCategory(payload)).unwrap();
      toast.success(`Category "${res.name}" created successfully`);
      setFormState(null);
    } catch (err: any) {
      toast.error(err || "Failed to create category");
    }
  };

  const handleUpdate = async (id: string, payload: UpdateCategoryPayload | FormData) => {
    try {
      const res = await dispatch(updateCategory({ id, payload })).unwrap();
      toast.success(`Category "${res.name}" updated successfully`);
      setFormState(null);
    } catch (err: any) {
      toast.error(err || "Failed to update category");
    }
  };

  const handleDeleteConfirm = async () => {
    if (!deleteTarget) return;
    try {
      await dispatch(deleteCategory(deleteTarget.id)).unwrap();
      toast.success(`Category "${deleteTarget.name}" removed successfully`);
      setDeleteTarget(null);
    } catch (err: any) {
      toast.error(err || "Failed to remove category");
    }
  };

  const handleStatusConfirm = async () => {
    if (!statusConfirm) return;
    const newStatus = statusConfirm.action === "inactivate" ? "inactive" : "active";
    try {
      await dispatch(changeCategoryStatus({ id: statusConfirm.id, status: newStatus })).unwrap();
      toast.success(
        `Category "${statusConfirm.name}" ${newStatus === "active" ? "activated" : "inactivated"} successfully`
      );
      setStatusConfirm(null);
    } catch (err: any) {
      toast.error(err || "Failed to update category status");
    }
  };

  // Find ancestor navigation name for a given node
  const findNavName = (node: CategoryNode): string => {
    if (node.navigationLabel) return node.navigationLabel;
    if (node.navigation === "used") return "Used Products";
    if (node.navigation === "new") return "New Products";
    return "New Products";
  };

  return (
    <div className="min-w-0">
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div>
          <h1 className="text-[20px] font-bold text-[#101828]">Category Management</h1>
          <p className="mt-1 text-[13px] text-[#667085]">Manage navigation categories in a structured hierarchy</p>
        </div>
        <button
          type="button"
          onClick={() => setFormState({ mode: "add" })}
          className="flex h-10 items-center gap-2 rounded-lg bg-[#1657D9] px-4 text-[13px] font-medium text-white transition-colors hover:bg-[#1445B0]"
        >
          <PlusCircleIcon />
          Add New Category
        </button>
      </div>

      <div className="mt-6 rounded-xl border border-[#E4E7EC] bg-white">
        <div className="flex items-center rounded-t-xl border-b border-[#E4E7EC] bg-[#EAF1FF] px-4 py-3 pr-6 text-[13px] font-medium text-[#475467]">
          <div className="flex-1">Categories</div>
          <div className="flex items-center gap-x-10 pl-6">
            <div className="w-9 shrink-0">Status</div>
            <div className="w-10 shrink-0 text-right">Products</div>
            <div className="w-24 shrink-0 text-right">Updated on</div>
            <div className="w-14 shrink-0 text-right">Action</div>
          </div>
        </div>

        <div>
          {loading && tree.length === 0 ? (
            <div className="divide-y divide-[#E4E7EC]">
              {Array.from({ length: 6 }).map((_, i) => (
                <div key={i} className="flex items-center justify-between px-4 py-3 animate-pulse">
                  <div className="flex items-center gap-3">
                    <div className="h-4 w-4 rounded bg-gray-200" />
                    <div className="h-4 w-40 rounded bg-gray-200" />
                  </div>
                  <div className="flex items-center gap-x-10">
                    <div className="h-5 w-9 rounded-full bg-gray-200" />
                    <div className="h-4 w-8 rounded bg-gray-200" />
                    <div className="h-4 w-20 rounded bg-gray-200" />
                    <div className="h-7 w-7 rounded-full bg-gray-200" />
                  </div>
                </div>
              ))}
            </div>
          ) : tree.length > 0 ? (
            tree.map((node) => (
              <CategoryRow
                key={node.id}
                category={node}
                depth={0}
                expanded={expanded}
                onToggleExpand={toggleExpand}
                onRequestToggleStatus={(node, isCurrentlyActive) => {
                  setOpenMenu(null);
                  setStatusConfirm({
                    id: node.id,
                    name: node.name,
                    action: isCurrentlyActive ? "inactivate" : "activate",
                  });
                }}
                openMenu={openMenu}
                setOpenMenu={setOpenMenu}
                onRequestDelete={(id, name) => {
                  setOpenMenu(null);
                  setDeleteTarget({ id, name });
                }}
                onRequestEdit={(node) => {
                  setOpenMenu(null);
                  setFormState({
                    mode: "edit",
                    target: {
                      id: node.id,
                      name: node.name,
                      type: typeof node.type === "string" ? node.type : undefined,
                      level: node.level,
                      description: node.description,
                      categoryThumbnail: node.categoryThumbnail || node.thumbnail,
                      navigation: node.navigation,
                      parentId: node.parentId,
                    },
                  });
                }}
                onRequestViewProducts={(node) => {
                  setOpenMenu(null);
                  setProductsDrawerTarget({
                    id: node.id,
                    name: node.name,
                    navigationName: findNavName(node),
                  });
                }}
              />
            ))
          ) : (
            <div className="px-4 py-12 text-center text-[14px] text-[#667085]">
              No categories found. Click &quot;Add New Category&quot; to create one.
            </div>
          )}
        </div>
      </div>

      {/* Drawer for Category Products */}
      <CategoryProductsDrawer
        open={productsDrawerTarget !== null}
        onClose={() => setProductsDrawerTarget(null)}
        categoryId={productsDrawerTarget?.id ?? null}
        categoryName={productsDrawerTarget?.name ?? "Category"}
        navigationName={productsDrawerTarget?.navigationName ?? "New Products"}
      />

      {/* Add / Edit Category Modal */}
      <AddCategoryModal
        key={formState?.mode === "edit" ? formState.target.id : "add"}
        open={formState !== null}
        onClose={() => setFormState(null)}
        tree={tree}
        onCreate={handleCreate}
        editTarget={formState?.mode === "edit" ? formState.target : null}
        onUpdate={handleUpdate}
        loading={actionLoading}
      />

      {/* Remove Category Confirmation */}
      <RemoveCategoryModal
        open={deleteTarget !== null}
        loading={actionLoading}
        onClose={() => setDeleteTarget(null)}
        onConfirm={handleDeleteConfirm}
      />

      {/* Change Status Confirmation */}
      <CategoryStatusModal
        open={statusConfirm !== null}
        action={statusConfirm?.action ?? "inactivate"}
        loading={actionLoading}
        onClose={() => setStatusConfirm(null)}
        onConfirm={handleStatusConfirm}
      />
    </div>
  );
}

function CategoryRow({
  category,
  depth,
  expanded,
  onToggleExpand,
  onRequestToggleStatus,
  openMenu,
  setOpenMenu,
  onRequestDelete,
  onRequestEdit,
  onRequestViewProducts,
}: {
  category: CategoryNode;
  depth: number;
  expanded: Set<string>;
  onToggleExpand: (id: string) => void;
  onRequestToggleStatus: (category: CategoryNode, currentStatus: boolean) => void;
  openMenu: string | null;
  setOpenMenu: (id: string | null) => void;
  onRequestDelete: (id: string, name: string) => void;
  onRequestEdit: (category: CategoryNode) => void;
  onRequestViewProducts: (category: CategoryNode) => void;
}) {
  const children = category.children || category.categories || category.subCategories || [];
  const hasChildren = Boolean(children.length > 0);
  const isExpanded = expanded.has(category.id);
  const isRoot = category.level === -1;
  const isNavigation = category.level === 0;
  const isTopTier = depth === 1 && hasChildren;
  const isActive = category.status === "active";

  const [imgError, setImgError] = useState(false);
  const rawThumbnail = category.categoryThumbnail || category.thumbnail;
  const thumbnail = getImageUrl(rawThumbnail);

  useEffect(() => {
    setImgError(false);
  }, [thumbnail]);

  return (
    <>
      <div
        className={`flex items-center border-b border-[#E4E7EC] px-4 py-2.5 pr-6 last:border-b-0 hover:bg-[#F5F7F9] ${
          openMenu === category.id ? "relative z-30" : "relative z-0"
        }`}
      >
        <div className="flex min-w-0 flex-1 items-center gap-1.5" style={{ paddingLeft: depth * 20 }}>
          {hasChildren ? (
            <button
              type="button"
              onClick={() => onToggleExpand(category.id)}
              className="flex h-5 w-5 shrink-0 items-center justify-center text-[#667085]"
              aria-label={isExpanded ? "Collapse" : "Expand"}
            >
              <TriangleDisclosureIcon className={`transition-transform ${isExpanded ? "" : "-rotate-90"}`} />
            </button>
          ) : (
            <span className="w-5 shrink-0" />
          )}

          {depth > 0 && (
            <>
              {isTopTier ? (
                <span className="shrink-0 text-[#F79009]">
                  <Image src="/assets/category-nav-arrow.png" alt="" width={16} height={16} />
                </span>
              ) : thumbnail && !imgError ? (
                <div className="relative h-10 w-10 shrink-0 overflow-hidden">
                  <img
                    src={thumbnail}
                    alt={category.name}
                    className="h-full w-full object-cover"
                    onError={() => setImgError(true)}
                  />
                </div>
              ) : (
                <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded border border-[#E4E7EC] bg-[#F5F7F9] text-[#98A2B3]">
                  {hasChildren ? <CategoriesIcon /> : <TagIcon />}
                </div>
              )}
            </>
          )}

          <span
            className={`truncate text-[13px] ${
              depth === 0 ? "font-semibold text-[#101828]" : "font-medium text-[#344054]"
            }`}
          >
            {category.name}
          </span>
        </div>

        <div className="flex items-center gap-x-10 pl-6">
          <div className="w-9 shrink-0">
            {!isRoot ? (
              <ToggleSwitch
                checked={isActive}
                onChange={() => onRequestToggleStatus(category, isActive)}
                ariaLabel={`Toggle ${category.name}`}
              />
            ) : (
              <span className="inline-block w-9" />
            )}
          </div>

          <div className="w-10 shrink-0 text-right text-[13px] text-[#475467]">
            {category.totalProducts ?? 0}
          </div>
          <div className="w-24 shrink-0 text-right text-[13px] text-[#475467]">
            {formatDate(category.updatedAt)}
          </div>

          <div className="flex w-14 shrink-0 justify-end">
            {!isRoot ? (
              <RowActionMenu
                open={openMenu === category.id}
                onToggle={() => setOpenMenu(openMenu === category.id ? null : category.id)}
                onClose={() => setOpenMenu(null)}
                isActive={isActive}
                isNavigation={isNavigation}
                onToggleStatus={() => onRequestToggleStatus(category, isActive)}
                onDelete={() => onRequestDelete(category.id, category.name)}
                onEdit={() => onRequestEdit(category)}
                onViewProducts={() => onRequestViewProducts(category)}
              />
            ) : (
              <span className="inline-block w-7" />
            )}
          </div>
        </div>
      </div>

      {hasChildren &&
        isExpanded &&
        children.map((child) => (
          <CategoryRow
            key={child.id}
            category={child}
            depth={depth + 1}
            expanded={expanded}
            onToggleExpand={onToggleExpand}
            onRequestToggleStatus={onRequestToggleStatus}
            openMenu={openMenu}
            setOpenMenu={setOpenMenu}
            onRequestDelete={onRequestDelete}
            onRequestEdit={onRequestEdit}
            onRequestViewProducts={onRequestViewProducts}
          />
        ))}
    </>
  );
}

function RowActionMenu({
  open,
  onToggle,
  onClose,
  isActive,
  isNavigation = false,
  onToggleStatus,
  onDelete,
  onEdit,
  onViewProducts,
}: {
  open: boolean;
  onToggle: () => void;
  onClose: () => void;
  isActive: boolean;
  isNavigation?: boolean;
  onToggleStatus: () => void;
  onDelete: () => void;
  onEdit: () => void;
  onViewProducts: () => void;
}) {
  const ref = useRef<HTMLDivElement | null>(null);
  useClickOutside(ref, onClose, open);
  const [openUpward, setOpenUpward] = useState(false);

  useEffect(() => {
    if (open && ref.current) {
      const rect = ref.current.getBoundingClientRect();
      const spaceBelow = window.innerHeight - rect.bottom;
      setOpenUpward(spaceBelow < 220);
    }
  }, [open]);

  const itemClass =
    "flex w-full items-center gap-2.5 whitespace-nowrap px-3.5 py-2 text-left text-[13px] font-medium hover:bg-[#F5F7F9]";

  return (
    <div ref={ref} className="relative">
      <button
        type="button"
        onClick={onToggle}
        className="flex h-7 w-7 items-center justify-center rounded-full text-[#667085] transition-colors hover:bg-[#F2F4F7]"
      >
        <KebabIcon />
      </button>
      {open && (
        <div
          className={`absolute right-0 z-50 min-w-[190px] rounded-lg border border-[#E4E7EC] bg-white py-1.5 shadow-[0_10px_24px_rgba(15,23,42,0.18)] ${
            openUpward ? "bottom-[calc(100%+4px)]" : "top-[calc(100%+4px)]"
          }`}
        >
          <button type="button" onClick={onViewProducts} className={`${itemClass} text-[#344054]`}>
            <EyeViewIcon />
            View Category Products
          </button>

          {!isNavigation && (
            <button type="button" onClick={onEdit} className={`${itemClass} text-[#344054]`}>
              <PencilIcon />
              Edit Category
            </button>
          )}

          {isActive ? (
            <>
              <button type="button" onClick={onToggleStatus} className={`${itemClass} text-[#344054]`}>
                <PowerIcon />
                Inactive Category
              </button>
              {!isNavigation && (
                <button type="button" onClick={onDelete} className={`${itemClass} text-[#DC2626]`}>
                  <TrashIcon />
                  Remove Category
                </button>
              )}
            </>
          ) : (
            <button type="button" onClick={onToggleStatus} className={`${itemClass} text-[#16A34A]`}>
              <PowerIcon />
              Reactivate Category
            </button>
          )}
        </div>
      )}
    </div>
  );
}
