"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import { menuApi } from "@/lib/api/menu";
import type { MenuItem } from "@/lib/api/menu";
import { useMenu } from "@/contexts/MenuContext";
import { useAuth } from "@/hooks/useAuth";
import { LoadingSpinner, LoadingOverlay } from "@/components/common/LoadingSpinner";
import { MenuFormModal } from "@/components/admin/MenuFormModal";
import { MenuCopyDialog } from "@/components/admin/MenuCopyDialog";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";

import { MenuScopePanel } from "@/components/admin/menu/MenuScopePanel";
import { MenuTreePanel } from "@/components/admin/menu/MenuTreePanel";
import { MenuOverviewPanel } from "@/components/admin/menu/MenuOverviewPanel";
import { MenuSettingsPanel } from "@/components/admin/menu/MenuSettingsPanel";

type Scope = "admin" | "user";
type View = "overview" | "settings";

export default function MenuPage() {
  const { refreshMenus } = useMenu();
  const { user } = useAuth();

  const [scope, setScope] = useState<Scope>("admin");
  const [adminMenus, setAdminMenus] = useState<MenuItem[]>([]);
  const [userMenus, setUserMenus] = useState<MenuItem[]>([]);
  const [selectedId, setSelectedId] = useState<string>("");
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  const [view, setView] = useState<View>("overview");
  const [searchText, setSearchText] = useState("");
  const [loading, setLoading] = useState(false);
  const [deleting, setDeleting] = useState(false);

  // 고급 편집 모달 (기존 MenuFormModal 재사용)
  const [formModalOpen, setFormModalOpen] = useState(false);
  const [formModalData, setFormModalData] = useState({
    menuId: "",
    parentId: "0",
    menu_type: "0",
    level: 0,
    parentCompanyCode: "",
  });

  const [copyDialogOpen, setCopyDialogOpen] = useState(false);
  const [copyTarget, setCopyTarget] = useState({ id: "", name: "" });

  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  const [deleteTargetId, setDeleteTargetId] = useState("");

  // Promise 기반 confirm 다이얼로그 (window.confirm 대체)
  const [confirmState, setConfirmState] = useState<{
    open: boolean;
    title: string;
    description: string;
    okLabel: string;
    cancelLabel: string;
    resolver: ((v: boolean) => void) | null;
  }>({
    open: false,
    title: "",
    description: "",
    okLabel: "확인",
    cancelLabel: "취소",
    resolver: null,
  });

  const confirmDialog = useCallback(
    (title: string, description: string, okLabel = "확인", cancelLabel = "취소") =>
      new Promise<boolean>((resolve) => {
        setConfirmState({ open: true, title, description, okLabel, cancelLabel, resolver: resolve });
      }),
    [],
  );

  const resolveConfirm = (ok: boolean) => {
    confirmState.resolver?.(ok);
    setConfirmState((s) => ({ ...s, open: false, resolver: null }));
  };

  const menus = scope === "admin" ? adminMenus : userMenus;

  const selectedMenu = useMemo(
    () => menus.find((m) => String(m.objid ?? m.OBJID) === selectedId),
    [menus, selectedId],
  );

  const parentName = useMemo(() => {
    if (!selectedMenu) return "";
    const parentId = String(selectedMenu.parent_obj_id ?? selectedMenu.PARENT_OBJ_ID ?? "0");
    if (parentId === "0") return "";
    const parent = menus.find((m) => String(m.objid ?? m.OBJID) === parentId);
    return parent ? (parent.menu_name_kor ?? parent.MENU_NAME_KOR ?? "") : "";
  }, [selectedMenu, menus]);

  const loadMenus = useCallback(
    async (showLoading = true) => {
      if (showLoading) setLoading(true);
      try {
        const [adminRes, userRes] = await Promise.all([
          menuApi.getAdminMenusForManagement(),
          menuApi.getUserMenusForManagement(),
        ]);
        if (adminRes.success && adminRes.data) setAdminMenus(adminRes.data);
        if (userRes.success && userRes.data) setUserMenus(userRes.data);
      } catch (e) {
        toast.error("메뉴 목록을 불러오는데 실패했습니다");
      } finally {
        if (showLoading) setLoading(false);
      }
    },
    [],
  );

  useEffect(() => {
    loadMenus(true);
  }, [loadMenus]);

  // 스코프 변경 시 선택/검색/탭 초기화
  useEffect(() => {
    setSelectedId("");
    setSearchText("");
    setView("overview");
  }, [scope]);

  const handleSelect = (id: string) => {
    const node = menus.find((m) => String(m.objid ?? m.OBJID) === id);
    setSelectedId(id);
    const lev = Number(node?.lev ?? node?.LEV ?? 1);
    setView(lev > 1 ? "settings" : "overview");
  };

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

  const handleMove = async (
    sourceId: string,
    targetId: string,
    pos: "before" | "after" | "into",
  ) => {
    const source = menus.find((m) => String(m.objid ?? m.OBJID) === sourceId);
    const target = menus.find((m) => String(m.objid ?? m.OBJID) === targetId);
    if (!source || !target) return;

    // 순환 방지: source가 target의 조상이면 거부
    const isAncestor = (aId: string, bId: string): boolean => {
      let cur = menus.find((m) => String(m.objid ?? m.OBJID) === bId);
      while (cur) {
        const pid = String(cur.parent_obj_id ?? cur.PARENT_OBJ_ID ?? "0");
        if (pid === "0") return false;
        if (pid === aId) return true;
        cur = menus.find((m) => String(m.objid ?? m.OBJID) === pid);
      }
      return false;
    };
    if (isAncestor(sourceId, targetId) || sourceId === targetId) {
      toast.error("자기 자신의 하위로 이동할 수 없습니다");
      return;
    }

    // 새 parent 결정
    let newParentId: string;
    if (pos === "into") {
      newParentId = String(target.objid ?? target.OBJID);
    } else {
      newParentId = String(target.parent_obj_id ?? target.PARENT_OBJ_ID ?? "0");
    }

    // parent 변경(=계층 이동) 시 사용자 확인
    const currentParentId = String(source.parent_obj_id ?? source.PARENT_OBJ_ID ?? "0");
    if (currentParentId !== newParentId) {
      const sourceName = source.menu_name_kor ?? source.MENU_NAME_KOR ?? "메뉴";
      const targetParentName =
        newParentId === "0"
          ? "최상위"
          : (() => {
              const p = menus.find((m) => String(m.objid ?? m.OBJID) === newParentId);
              return p ? (p.menu_name_kor ?? p.MENU_NAME_KOR ?? "알 수 없음") : "알 수 없음";
            })();
      const ok = await confirmDialog(
        "메뉴 계층 이동",
        `"${sourceName}" 메뉴를 "${targetParentName}" 하위로 이동합니다. 계층이 변경되며 되돌리려면 다시 드래그해야 합니다. 진행하시겠습니까?`,
        "이동",
        "취소",
      );
      if (!ok) return;
    }

    // 새 parent의 모든 형제(source 제외)를 seq 순으로 정렬
    const siblings = menus
      .filter((m) => String(m.parent_obj_id ?? m.PARENT_OBJ_ID ?? "0") === newParentId)
      .filter((m) => String(m.objid ?? m.OBJID) !== sourceId)
      .sort((a, b) => Number(a.seq ?? a.SEQ ?? 0) - Number(b.seq ?? b.SEQ ?? 0));

    // 삽입 위치 결정
    let insertIdx: number;
    if (pos === "into") {
      insertIdx = siblings.length;
    } else {
      const targetIdx = siblings.findIndex((m) => String(m.objid ?? m.OBJID) === targetId);
      insertIdx = pos === "before" ? targetIdx : targetIdx + 1;
    }

    // 재구성된 순서 (source 포함)
    const reordered = [...siblings];
    reordered.splice(insertIdx, 0, source);

    // 각 형제 seq 0,1,2,... 재부여 + 순차 업데이트 (순서 보장)
    try {
      for (let i = 0; i < reordered.length; i++) {
        const m = reordered[i];
        const id = String(m.objid ?? m.OBJID);
        const isSource = id === sourceId;
        // 기존 seq와 동일하면 skip (source는 parent 변경 가능성 때문에 항상 업데이트)
        const curSeq = Number(m.seq ?? m.SEQ ?? 0);
        if (!isSource && curSeq === i) continue;
        const payload = {
          objid: id,
          parentObjId: isSource
            ? newParentId
            : String(m.parent_obj_id ?? m.PARENT_OBJ_ID ?? "0"),
          menuNameKor: m.menu_name_kor ?? m.MENU_NAME_KOR ?? "",
          menuUrl: m.menu_url ?? m.MENU_URL ?? "",
          menuDesc: m.menu_desc ?? m.MENU_DESC ?? "",
          seq: i,
          menu_type: String(m.menu_type ?? m.MENU_TYPE ?? (scope === "admin" ? "0" : "1")),
          status: (m.status ?? m.STATUS ?? "active").toString(),
          company_code: m.company_code ?? m.COMPANY_CODE ?? "*",
          langKey: m.lang_key ?? m.LANG_KEY ?? undefined,
          menuIcon: m.menu_icon ?? m.MENU_ICON ?? undefined,
        };
        await menuApi.updateMenu(id, payload);
      }
      toast.success("이동되었습니다");
      await loadMenus(false);
      await refreshMenus();
    } catch (e) {
      toast.error("이동 중 오류가 발생했습니다");
    }
  };

  const handleAddTop = () => {
    setFormModalData({
      menuId: "",
      parentId: "0",
      menu_type: scope === "admin" ? "0" : "1",
      level: 1,
      parentCompanyCode: "",
    });
    setFormModalOpen(true);
  };

  const handleOpenAdvanced = (menuId: string) => {
    const node = menus.find((m) => String(m.objid ?? m.OBJID) === menuId);
    if (!node) return;
    setFormModalData({
      menuId,
      parentId: String(node.parent_obj_id ?? node.PARENT_OBJ_ID ?? "0"),
      menu_type: String(node.menu_type ?? node.MENU_TYPE ?? "1"),
      level: Number(node.lev ?? node.LEV ?? 1),
      parentCompanyCode: node.company_code ?? node.COMPANY_CODE ?? "",
    });
    setFormModalOpen(true);
  };

  const handleFormSuccess = async () => {
    await loadMenus(false);
    await refreshMenus();
  };

  const handleSavedInline = async () => {
    await loadMenus(false);
    await refreshMenus();
  };

  const requestDelete = (menuId: string) => {
    setDeleteTargetId(menuId);
    setDeleteDialogOpen(true);
  };

  const confirmDelete = async () => {
    setDeleting(true);
    try {
      const resp = await menuApi.deleteMenu(deleteTargetId);
      if (resp.success) {
        toast.success(resp.message || "삭제되었습니다");
        if (selectedId === deleteTargetId) {
          setSelectedId("");
          setView("overview");
        }
        await loadMenus(false);
        await refreshMenus();
      } else {
        toast.error(resp.message || "삭제 실패");
      }
    } catch (e) {
      toast.error("삭제 중 오류가 발생했습니다");
    } finally {
      setDeleting(false);
      setDeleteDialogOpen(false);
      setDeleteTargetId("");
    }
  };

  if (loading) {
    return (
      <div className="flex h-64 items-center justify-center">
        <LoadingSpinner />
      </div>
    );
  }

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
      {/* 페이지 헤더 */}
      <div
        style={{
          padding: "1.1rem 1.4rem .9rem",
          borderBottom: "1px solid var(--v5-border)",
          display: "flex",
          alignItems: "flex-end",
          justifyContent: "space-between",
          gap: "1rem",
          flexShrink: 0,
        }}
      >
        <div>
          <h1
            style={{
              margin: 0,
              fontSize: "1.1rem",
              fontWeight: 700,
              letterSpacing: "-.02em",
              color: "var(--v5-text)",
            }}
          >
            메뉴 관리
          </h1>
          <p
            style={{
              margin: ".3rem 0 0",
              fontSize: ".72rem",
              color: "var(--v5-text-muted)",
            }}
          >
            트리에서 항목을 선택하면 우측에서 편집합니다.
          </p>
        </div>
      </div>

      <LoadingOverlay isLoading={deleting} text="삭제 중...">
        <div className="v5-mm">
          <MenuScopePanel
            scope={scope}
            adminCount={adminMenus.length}
            userCount={userMenus.length}
            onChange={setScope}
          />

          <MenuTreePanel
            menus={menus}
            selectedId={selectedId}
            expandedIds={expanded}
            searchText={searchText}
            onSelect={handleSelect}
            onToggleExpand={handleToggleExpand}
            onSearchChange={setSearchText}
            onAddTop={handleAddTop}
            onMove={handleMove}
          />

          <section className="v5-mm-col v5-mm-col-detail">
            <div className="v5-mm-vt">
              <div className="v5-mm-vt-list">
                <button
                  className={`v5-mm-vt-btn${view === "overview" ? " on" : ""}`}
                  onClick={() => setView("overview")}
                >
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                    <rect x="3" y="3" width="7" height="7" rx="1" />
                    <rect x="14" y="3" width="7" height="7" rx="1" />
                    <rect x="3" y="14" width="7" height="7" rx="1" />
                    <rect x="14" y="14" width="7" height="7" rx="1" />
                  </svg>
                  Overview
                </button>
                <button
                  className={`v5-mm-vt-btn${view === "settings" ? " on" : ""}`}
                  onClick={() => setView("settings")}
                  disabled={!selectedMenu}
                >
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                    <circle cx="12" cy="12" r="3" />
                    <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
                  </svg>
                  Settings
                </button>
              </div>
            </div>

            {view === "overview" && <MenuOverviewPanel menus={menus} selectedId={selectedId} />}
            {view === "settings" && selectedMenu && (
              <MenuSettingsPanel
                menu={selectedMenu}
                parentName={parentName}
                onSaved={handleSavedInline}
                onDelete={requestDelete}
                onOpenAdvanced={handleOpenAdvanced}
              />
            )}
            {view === "settings" && !selectedMenu && (
              <div className="v5-mm-pane on v5-mm-pane-wrap">
                <div className="v5-mm-empty">
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
                    <circle cx="12" cy="12" r="3" />
                    <path d="M12 1v6M12 17v6M4.2 4.2l4.3 4.3M15.5 15.5l4.3 4.3M1 12h6M17 12h6M4.2 19.8l4.3-4.3M15.5 8.5l4.3-4.3" />
                  </svg>
                  <div>트리에서 L2/L3 항목을 선택하세요</div>
                </div>
              </div>
            )}
          </section>
        </div>
      </LoadingOverlay>

      <MenuFormModal
        isOpen={formModalOpen}
        onClose={() => setFormModalOpen(false)}
        onSuccess={handleFormSuccess}
        menuId={formModalData.menuId}
        parentId={formModalData.parentId}
        menuType={formModalData.menu_type}
        level={formModalData.level}
        parentCompanyCode={formModalData.parentCompanyCode}
        uiTexts={{}}
      />

      <MenuCopyDialog
        menuObjid={copyTarget.id ? parseInt(copyTarget.id, 10) : null}
        menuName={copyTarget.name}
        open={copyDialogOpen}
        onOpenChange={setCopyDialogOpen}
        onCopyComplete={async () => {
          await loadMenus(false);
          toast.success("메뉴 복사가 완료되었습니다");
        }}
      />

      <AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>메뉴 삭제</AlertDialogTitle>
            <AlertDialogDescription>
              해당 메뉴를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>취소</AlertDialogCancel>
            <AlertDialogAction onClick={confirmDelete}>삭제</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <AlertDialog
        open={confirmState.open}
        onOpenChange={(o) => {
          if (!o) resolveConfirm(false);
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>{confirmState.title}</AlertDialogTitle>
            <AlertDialogDescription>{confirmState.description}</AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onClick={() => resolveConfirm(false)}>
              {confirmState.cancelLabel}
            </AlertDialogCancel>
            <AlertDialogAction onClick={() => resolveConfirm(true)}>
              {confirmState.okLabel}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
