"use client";

import { useState, useEffect, useCallback, useTransition } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { RefreshCw, Plus, Loader2 } from "lucide-react";
import { DomainTabs } from "./domain-tabs";
import { MenuTree } from "./menu-tree";
import { EditNodeDialog } from "./edit-node-dialog";
import { AddNodeDialog } from "./add-node-dialog";
import { MoveToDialog } from "./move-to-dialog";
import { UnassignedMenusPanel } from "./unassigned-menus-panel";
import {
  getMenuTreeForAdmin,
  createMenuGroup,
  createGroup,
  createTopLevelMenu,
  updateNode,
  moveNodeUp,
  moveNodeDown,
  moveNodeToParent,
  getAvailableParents,
  assignMenuToGroup,
  activateAsTopLevelMenu,
  syncDiscoveredMenus,
} from "../service";
import type { 
  MenuDomain, 
  MenuTreeNode, 
  MenuTreeAdminResult, 
  UpdateNodeInput,
  CreateMenuGroupInput,
  CreateGroupInput,
  CreateTopLevelMenuInput,
} from "../types";

interface MenuTreeManagerProps {
  initialDomain?: MenuDomain;
}

export function MenuTreeManager({ initialDomain = "evcp" }: MenuTreeManagerProps) {
  const [domain, setDomain] = useState<MenuDomain>(initialDomain);
  const [data, setData] = useState<MenuTreeAdminResult | null>(null);
  const [isInitialLoading, setIsInitialLoading] = useState(true);
  const [isPending, startTransition] = useTransition();
  
  // Dialog states
  const [editDialogOpen, setEditDialogOpen] = useState(false);
  const [editingNode, setEditingNode] = useState<MenuTreeNode | null>(null);
  const [addDialogOpen, setAddDialogOpen] = useState(false);
  const [addDialogType, setAddDialogType] = useState<"menu_group" | "group" | "top_level_menu">("menu_group");
  const [addGroupParentId, setAddGroupParentId] = useState<number | undefined>(undefined);
  
  // Move dialog state
  const [moveDialogOpen, setMoveDialogOpen] = useState(false);
  const [movingNode, setMovingNode] = useState<MenuTreeNode | null>(null);
  const [availableParents, setAvailableParents] = useState<{ id: number | null; title: string; depth: number }[]>([]);
  
  // Tree expansion state
  const [expandedIds, setExpandedIds] = useState<Set<number>>(new Set());

  // Load data using server action
  const loadData = useCallback(async (isRefresh = false) => {
    if (!isRefresh) {
      setIsInitialLoading(true);
    }
    try {
      const result = await getMenuTreeForAdmin(domain);
      setData(result);
    } catch (error) {
      console.error("Error loading menu tree:", error);
      toast.error("Failed to load menu tree");
    } finally {
      setIsInitialLoading(false);
    }
  }, [domain]);

  useEffect(() => {
    setExpandedIds(new Set());
    loadData();
  }, [loadData]);

  const handleSync = async () => {
    startTransition(async () => {
      try {
        const result = await syncDiscoveredMenus(domain);
        toast.success(`Sync complete: ${result.added} menus added`);
        loadData(true);
      } catch (error) {
        console.error("Error syncing menus:", error);
        toast.error("Failed to sync menus");
      }
    });
  };

  const handleEdit = (node: MenuTreeNode) => {
    setEditingNode(node);
    setEditDialogOpen(true);
  };

  const handleSaveEdit = async (nodeId: number, input: UpdateNodeInput) => {
    startTransition(async () => {
      try {
        await updateNode(nodeId, input);
        toast.success("Saved successfully");
        loadData(true);
      } catch (error) {
        console.error("Error updating node:", error);
        toast.error("Failed to save");
      }
    });
  };

  // Move up (within same parent)
  const handleMoveUp = async (nodeId: number) => {
    startTransition(async () => {
      try {
        await moveNodeUp(nodeId);
        loadData(true);
      } catch (error) {
        console.error("Error moving node up:", error);
        toast.error("Failed to move");
      }
    });
  };

  // Move down (within same parent)
  const handleMoveDown = async (nodeId: number) => {
    startTransition(async () => {
      try {
        await moveNodeDown(nodeId);
        loadData(true);
      } catch (error) {
        console.error("Error moving node down:", error);
        toast.error("Failed to move");
      }
    });
  };

  // Open move to dialog
  const handleOpenMoveDialog = async (node: MenuTreeNode) => {
    setMovingNode(node);
    try {
      const parents = await getAvailableParents(node.id, domain, node.nodeType);
      setAvailableParents(parents);
      setMoveDialogOpen(true);
    } catch (error) {
      console.error("Error loading available parents:", error);
      toast.error("Failed to load move options");
    }
  };

  // Execute move to different parent
  const handleMoveTo = async (newParentId: number | null) => {
    if (!movingNode) return;
    startTransition(async () => {
      try {
        await moveNodeToParent(movingNode.id, newParentId);
        toast.success("Moved successfully");
        setMoveDialogOpen(false);
        setMovingNode(null);
        loadData(true);
      } catch (error) {
        console.error("Error moving node:", error);
        toast.error("Failed to move");
      }
    });
  };

  const handleAddMenuGroup = () => {
    setAddDialogType("menu_group");
    setAddGroupParentId(undefined);
    setAddDialogOpen(true);
  };

  const handleAddGroup = (parentId: number) => {
    setAddDialogType("group");
    setAddGroupParentId(parentId);
    setAddDialogOpen(true);
  };

  const handleAddTopLevelMenu = () => {
    setAddDialogType("top_level_menu");
    setAddGroupParentId(undefined);
    setAddDialogOpen(true);
  };

  const handleSaveAdd = async (
    input: CreateMenuGroupInput | CreateGroupInput | CreateTopLevelMenuInput
  ) => {
    startTransition(async () => {
      try {
        if (addDialogType === "menu_group") {
          await createMenuGroup(domain, input as CreateMenuGroupInput);
        } else if (addDialogType === "group") {
          await createGroup(domain, input as CreateGroupInput);
        } else if (addDialogType === "top_level_menu") {
          await createTopLevelMenu(domain, input as CreateTopLevelMenuInput);
        }
        toast.success("Created successfully");
        loadData(true);
      } catch (error) {
        console.error("Error creating node:", error);
        toast.error("Failed to create");
      }
    });
  };

  const handleAssign = async (menuId: number, groupId: number) => {
    startTransition(async () => {
      try {
        await assignMenuToGroup(menuId, groupId);
        toast.success("Assigned successfully");
        loadData(true);
      } catch (error) {
        console.error("Error assigning menu:", error);
        toast.error("Failed to assign");
      }
    });
  };

  const handleActivateAsTopLevel = async (menuId: number) => {
    startTransition(async () => {
      try {
        await activateAsTopLevelMenu(menuId);
        toast.success("Activated as top-level menu");
        loadData(true);
      } catch (error) {
        console.error("Error activating as top level:", error);
        toast.error("Failed to activate");
      }
    });
  };

  // Build list of available groups for assignment
  const getAvailableGroups = () => {
    if (!data) return [];
    
    const groups: { id: number; title: string; parentTitle?: string }[] = [];
    
    for (const node of data.tree) {
      if (node.nodeType !== 'menu_group') continue;
      
      groups.push({ id: node.id, title: node.titleKo });
      
      if (node.children) {
        for (const child of node.children) {
          if (child.nodeType === "group") {
            groups.push({
              id: child.id,
              title: child.titleKo,
              parentTitle: node.titleKo,
            });
          }
        }
      }
    }
    
    return groups;
  };

  if (isInitialLoading) {
    return (
      <div className="flex items-center justify-center h-96">
        <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <DomainTabs value={domain} onChange={setDomain} />
        <div className="flex items-center gap-2">
          {/* [jh] I've commented this button.. */}
          {/* <Button variant="outline" size="sm" onClick={handleSync} disabled={isPending}>
            <RefreshCw className={`mr-2 h-4 w-4 ${isPending ? "animate-spin" : ""}`} />
            Sync Pages
          </Button> */}
          <Button variant="outline" size="sm" onClick={handleAddTopLevelMenu} disabled={isPending}>
            <Plus className="mr-2 h-4 w-4" />
            Add Top-Level Menu
          </Button>
          <Button size="sm" onClick={handleAddMenuGroup} disabled={isPending}>
            <Plus className="mr-2 h-4 w-4" />
            Add Menu Group
          </Button>
        </div>
      </div>

      {/* Main Content */}
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
        {/* Menu Tree */}
        <div className="lg:col-span-2">
          <Card>
            <CardHeader>
              <CardTitle>{domain === "evcp" ? "EVCP" : "Partners"} Menu Structure</CardTitle>
              <CardDescription>
                Use arrow buttons to reorder, or click Move To to change parent.
              </CardDescription>
            </CardHeader>
            <CardContent>
              {data?.tree && data.tree.length > 0 ? (
                <MenuTree
                  nodes={data.tree}
                  onEdit={handleEdit}
                  onMoveUp={handleMoveUp}
                  onMoveDown={handleMoveDown}
                  onMoveTo={handleOpenMoveDialog}
                  onAddGroup={handleAddGroup}
                  expandedIds={expandedIds}
                  onExpandedIdsChange={setExpandedIds}
                  isPending={isPending}
                />
              ) : (
                <p className="text-sm text-muted-foreground text-center py-8">
                  No menus. Add one using the buttons above.
                </p>
              )}
            </CardContent>
          </Card>
        </div>

        {/* Unassigned Menus */}
        <div className="lg:col-span-1">
          <UnassignedMenusPanel
            menus={data?.unassigned || []}
            onAssign={handleAssign}
            onActivateAsTopLevel={handleActivateAsTopLevel}
            onEdit={handleEdit}
            availableGroups={getAvailableGroups()}
          />
        </div>
      </div>

      {/* Dialogs */}
      <EditNodeDialog
        open={editDialogOpen}
        onOpenChange={setEditDialogOpen}
        node={editingNode}
        onSave={handleSaveEdit}
      />

      <AddNodeDialog
        open={addDialogOpen}
        onOpenChange={setAddDialogOpen}
        type={addDialogType}
        domain={domain}
        parentId={addGroupParentId}
        onSave={handleSaveAdd}
      />

      <MoveToDialog
        open={moveDialogOpen}
        onOpenChange={setMoveDialogOpen}
        node={movingNode}
        availableParents={availableParents}
        onMove={handleMoveTo}
      />
    </div>
  );
}
