"use client";

import { useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { LoadingSpinner } from "@/components/common/LoadingSpinner";
import { CodeFormModal } from "./CodeFormModal";
import { SortableCodeItem } from "./SortableCodeItem";
import { AlertModal } from "@/components/common/AlertModal";
import { Search, Plus } from "lucide-react";
import { useDeleteCodeDetail, useUpdateCodeDetail, useCodeDetailTree } from "@/hooks/queries/useCodeDetail";
import type { CodeDetail } from "@/types/commonCode";
import { DndContext, DragOverlay } from "@dnd-kit/core";
import { SortableContext, verticalListSortingStrategy, arrayMove } from "@dnd-kit/sortable";
import { useDragAndDrop } from "@/hooks/useDragAndDrop";

interface CodeDetailPanelProps {
  codeInfo: string;
}

/**
 * 디테일 트리 패널.
 *
 * BE 가 `/api/common-codes/detail?code_info=X` 로 depth+sort_order 평탄화 리스트를 내려준다.
 * FE 는 parent_detail_id 로 children 맵을 만들어 indent + collapse 처리.
 * sort_order 변경은 형제 단위 reorder → 각 행 update PUT 으로 직렬 호출.
 */
export function CodeDetailPanel({ codeInfo }: CodeDetailPanelProps) {
  const [searchTerm, setSearchTerm] = useState("");
  const [showActiveOnly, setShowActiveOnly] = useState(false);

  const treeQuery = useCodeDetailTree(codeInfo || undefined, {
    search: searchTerm || undefined,
    active: showActiveOnly || undefined,
  });
  const rows: CodeDetail[] = useMemo(() => treeQuery.data || [], [treeQuery.data]);
  const isLoading = treeQuery.isLoading;
  const error = treeQuery.error;

  const deleteMutation = useDeleteCodeDetail();
  const updateMutation = useUpdateCodeDetail();

  /** parent_detail_id → children */
  const childrenMap = useMemo(() => {
    const map = new Map<string, CodeDetail[]>();
    for (const row of rows) {
      const key = row.parent_detail_id == null ? "ROOT" : String(row.parent_detail_id);
      const list = map.get(key) || [];
      list.push(row);
      map.set(key, list);
    }
    return map;
  }, [rows]);

  // 접기/펼치기 (code_detail_id Set)
  const [collapsed, setCollapsed] = useState<Set<string>>(new Set());
  const toggleExpand = (id: string) => {
    setCollapsed((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  // 부모 행 중 하나라도 접혀있으면 자식 숨김
  const isRowVisible = (row: CodeDetail): boolean => {
    let parentId = row.parent_detail_id;
    while (parentId != null) {
      if (collapsed.has(String(parentId))) return false;
      const parentRow = rows.find((r) => String(r.code_detail_id) === String(parentId));
      parentId = parentRow ? parentRow.parent_detail_id : null;
    }
    return true;
  };

  const visibleRows = useMemo(() => rows.filter(isRowVisible), [rows, collapsed]);

  // 모달 상태
  const [showFormModal, setShowFormModal] = useState(false);
  const [editingRow, setEditingRow] = useState<CodeDetail | null>(null);
  const [defaultParentDetailId, setDefaultParentDetailId] = useState<number | null>(null);
  const [showDeleteModal, setShowDeleteModal] = useState(false);
  const [deletingRow, setDeletingRow] = useState<CodeDetail | null>(null);

  // sort_order 재할당 (형제 단위) — 드래그 결과를 PUT 으로 직렬 호출
  const dragAndDrop = useDragAndDrop<CodeDetail>({
    items: visibleRows,
    getItemId: (row) => String(row.code_detail_id),
    onReorder: async (reordered) => {
      // visibleRows 기준으로 재정렬. 형제만 reorder 의미가 있으므로
      // parent_detail_id 가 같은 그룹별로 처리.
      const idMap = new Map<string, number>();
      reordered.forEach(({ id, sortOrder }) => idMap.set(id, sortOrder));

      // 같은 부모 안의 형제만 묶어서 정렬
      const byParent = new Map<string, CodeDetail[]>();
      for (const row of visibleRows) {
        const parentKey =
          row.parent_detail_id == null ? "ROOT" : String(row.parent_detail_id);
        const list = byParent.get(parentKey) || [];
        list.push(row);
        byParent.set(parentKey, list);
      }

      for (const list of byParent.values()) {
        const sorted = [...list].sort((a, b) => {
          const ao = idMap.get(String(a.code_detail_id)) ?? a.sort_order ?? 0;
          const bo = idMap.get(String(b.code_detail_id)) ?? b.sort_order ?? 0;
          return ao - bo;
        });
        for (let i = 0; i < sorted.length; i++) {
          const row = sorted[i];
          const nextOrder = (i + 1) * 10;
          if ((row.sort_order ?? 0) === nextOrder) continue;
          await updateMutation.mutateAsync({
            codeDetailId: row.code_detail_id,
            data: {
              code_info: row.code_info,
              parent_detail_id: row.parent_detail_id ?? null,
              code_value: row.code_value,
              code_name: row.code_name,
              code_name_eng: row.code_name_eng || "",
              description: row.description || "",
              sort_order: nextOrder,
              is_active: row.is_active || "Y",
            },
          });
        }
      }
    },
  });

  const handleNew = () => {
    setEditingRow(null);
    setDefaultParentDetailId(null);
    setShowFormModal(true);
  };

  const handleEdit = (row: CodeDetail) => {
    setEditingRow(row);
    setDefaultParentDetailId(null);
    setShowFormModal(true);
  };

  const handleAddChild = (parent: CodeDetail) => {
    setEditingRow(null);
    setDefaultParentDetailId(Number(parent.code_detail_id));
    setShowFormModal(true);
  };

  const handleDelete = (row: CodeDetail) => {
    setDeletingRow(row);
    setShowDeleteModal(true);
  };

  const handleConfirmDelete = async () => {
    if (!deletingRow) return;
    try {
      await deleteMutation.mutateAsync(deletingRow.code_detail_id);
      setShowDeleteModal(false);
      setDeletingRow(null);
    } catch (error) {
      console.error("디테일 삭제 실패:", error);
    }
  };

  if (!codeInfo) {
    return (
      <div className="flex h-96 items-center justify-center">
        <p className="text-sm text-muted-foreground">그룹을 선택하세요</p>
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex h-96 items-center justify-center">
        <div className="text-center">
          <p className="text-sm font-semibold text-destructive">
            디테일을 불러오는 중 오류가 발생했습니다.
          </p>
          <Button
            variant="outline"
            onClick={() => window.location.reload()}
            className="mt-4 h-10 text-sm font-medium"
          >
            다시 시도
          </Button>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-full flex-col space-y-4">
      <div className="space-y-3">
        <div className="flex items-center gap-2">
          <div className="relative w-full sm:w-[300px]">
            <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              placeholder="디테일 검색..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="h-10 pl-10 text-sm"
            />
          </div>
          <Button onClick={handleNew} className="h-10 gap-2 text-sm font-medium">
            <Plus className="h-4 w-4" />
            등록
          </Button>
        </div>

        <div className="flex items-center gap-2">
          <input
            type="checkbox"
            id="activeOnlyDetail"
            checked={showActiveOnly}
            onChange={(e) => setShowActiveOnly(e.target.checked)}
            className="h-4 w-4 rounded border-input"
          />
          <label htmlFor="activeOnlyDetail" className="text-sm text-muted-foreground">
            활성만 표시
          </label>
        </div>
      </div>

      <div className="space-y-3">
        {isLoading ? (
          <div className="flex h-32 items-center justify-center">
            <LoadingSpinner />
          </div>
        ) : visibleRows.length === 0 ? (
          <div className="flex h-32 items-center justify-center">
            <p className="text-sm text-muted-foreground">
              {rows.length === 0 ? "디테일이 없습니다." : "검색 결과가 없습니다."}
            </p>
          </div>
        ) : (
          <DndContext {...dragAndDrop.dndContextProps}>
            <SortableContext
              items={visibleRows.map((r) => String(r.code_detail_id))}
              strategy={verticalListSortingStrategy}
            >
              {visibleRows.map((row) => {
                const idStr = String(row.code_detail_id);
                const children = childrenMap.get(idStr) || [];
                const hasChildren = children.length > 0;
                const isExpanded = !collapsed.has(idStr);

                return (
                  <SortableCodeItem
                    key={idStr}
                    row={row}
                    onEdit={() => handleEdit(row)}
                    onDelete={() => handleDelete(row)}
                    onAddChild={() => handleAddChild(row)}
                    hasChildren={hasChildren}
                    childCount={children.length}
                    isExpanded={isExpanded}
                    onToggleExpand={() => toggleExpand(idStr)}
                  />
                );
              })}
            </SortableContext>

            <DragOverlay dropAnimation={null}>
              {dragAndDrop.activeItem ? (
                <div className="cursor-grabbing rounded-lg border bg-card p-4 shadow-lg">
                  <div className="flex items-start justify-between">
                    <div className="min-w-0 flex-1">
                      <div className="flex items-center gap-2">
                        <h4 className="text-sm font-semibold">
                          {dragAndDrop.activeItem.code_name}
                        </h4>
                        <Badge
                          variant={dragAndDrop.activeItem.is_active === "Y" ? "default" : "secondary"}
                        >
                          {dragAndDrop.activeItem.is_active === "Y" ? "활성" : "비활성"}
                        </Badge>
                      </div>
                      <p className="mt-1 text-xs text-muted-foreground">
                        {dragAndDrop.activeItem.code_value}
                      </p>
                    </div>
                  </div>
                </div>
              ) : null}
            </DragOverlay>
          </DndContext>
        )}
      </div>

      {showFormModal && (
        <CodeFormModal
          isOpen={showFormModal}
          onClose={() => {
            setShowFormModal(false);
            setEditingRow(null);
            setDefaultParentDetailId(null);
          }}
          codeInfo={codeInfo}
          editingRow={editingRow}
          allRows={rows}
          defaultParentDetailId={defaultParentDetailId}
        />
      )}

      {showDeleteModal && (
        <AlertModal
          isOpen={showDeleteModal}
          onClose={() => setShowDeleteModal(false)}
          type="error"
          title="디테일 삭제"
          message="정말로 이 코드를 삭제하시겠습니까? 하위 코드도 모두 함께 삭제됩니다 (CASCADE)."
          confirmText="삭제"
          onConfirm={handleConfirmDelete}
        />
      )}
    </div>
  );
}

// `arrayMove` import 유지 위해 keep no-op (트리 reorder 로직에서 향후 활용 가능)
void arrayMove;
