"use client";

// 프로젝트관리 > 제품구분_WBS관리 통합 팝업
// wace WBSExcelImportPopUp.jsp (613줄) 1:1 이식
// - 트리 CRUD (추가/하위추가/삭제) + 수준 1/2/3 자동 번호 + 엑셀 임포트 + 템플릿 다운로드 + 저장
// - 헤더(제품구분/제목): 수정 모드에서 disabled (wace mergeExcelUploadWBS는 헤더 UPDATE 안 함)

import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { CommCodeSelect } from "@/components/common/CommCodeSelect";
import { Loader2, Download, Plus, CornerDownRight, Trash2, Save, Upload } from "lucide-react";
import { toast } from "sonner";
import { wbsTemplateApi, WbsTaskInput } from "@/lib/api/wbsTemplate";

const PRODUCT_GROUP = "0000001";
const TEMPLATE_DOWNLOAD_URL = "/templates/WBS_EXCEL_IMPORT_TEMPLATE.xlsx";

// 클라이언트 행 모델
interface WbsRow {
  objid: string;         // 클라이언트 임시 ID (UUID) — 저장 시 그대로 DB OBJID
  depth: number;         // 0=TOTAL, 1~3
  unitNo: string;        // "1", "1.1", "1.1.1" (자동 renumber로 채움)
  taskName: string;
  checked: boolean;
}

interface Props {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  templateObjId: string | null;       // null=신규
  defaultProduct: string;             // 신규 시 메인의 검색 product
  onSaved: () => void;
}

function newObjId(): string {
  return crypto.randomUUID();
}

function makeTotalRow(): WbsRow {
  return { objid: newObjId(), depth: 0, unitNo: "0", taskName: "TOTAL", checked: false };
}

export function WbsTemplateDialog({ open, onOpenChange, templateObjId, defaultProduct, onSaved }: Props) {
  const isEditMode = !!templateObjId;
  const fileInputRef = useRef<HTMLInputElement>(null);

  const [product, setProduct] = useState<string>("");
  const [title, setTitle] = useState<string>("");
  const [rows, setRows] = useState<WbsRow[]>([]);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);

  // ─── 모드 분기 (wace WBSExcelImportPopUp.jsp:21-30) ──────
  useEffect(() => {
    if (!open) return;
    if (isEditMode && templateObjId) {
      loadExistingTasks(templateObjId);
    } else {
      setProduct(defaultProduct);
      setTitle("");
      setRows([makeTotalRow()]);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  const loadExistingTasks = async (objid: string) => {
    setLoading(true);
    try {
      const detail = await wbsTemplateApi.detail(objid);
      if (!detail) {
        toast.error("템플릿을 찾을 수 없습니다.");
        onOpenChange(false);
        return;
      }
      setProduct(detail.master.product_objid);
      setTitle(detail.master.title);

      // wace loadExistingTasks 1:1: TASK_LEVEL=0 → TOTAL 행, 그 외 depth/unit_no 매핑
      const list: WbsRow[] = detail.tasks.map((t) => {
        const depth = parseInt(t.task_level, 10);
        if (depth === 0) {
          return { objid: t.objid, depth: 0, unitNo: "0", taskName: t.task_name || "TOTAL", checked: false };
        }
        return {
          objid: t.objid,
          depth,
          unitNo: t.unit_no || "",
          taskName: t.task_name || "",
          checked: false,
        };
      });
      // TOTAL이 없을 경우 보강
      if (!list.some((r) => r.depth === 0)) list.unshift(makeTotalRow());
      setRows(list);
    } catch (e: any) {
      toast.error(e?.response?.data?.message ?? e?.message ?? "조회 실패");
      onOpenChange(false);
    } finally {
      setLoading(false);
    }
  };

  // ─── 트리 동작 ─────────────────────────────────────────

  // wace renumberAllRows 1:1: depth별 카운터로 1.1.1 형식 재생성
  const renumberRows = useCallback((arr: WbsRow[]): WbsRow[] => {
    const counters = [0, 0, 0];
    return arr.map((r) => {
      if (r.depth === 0) return r;
      const d = r.depth;
      if (d === 1) { counters[0] += 1; counters[1] = 0; counters[2] = 0; }
      else if (d === 2) { counters[1] += 1; counters[2] = 0; }
      else if (d === 3) { counters[2] += 1; }
      const unit = d === 1 ? `${counters[0]}`
                 : d === 2 ? `${counters[0]}.${counters[1]}`
                 : `${counters[0]}.${counters[1]}.${counters[2]}`;
      return { ...r, unitNo: unit };
    });
  }, []);

  // 마지막 후손 인덱스 (wace findLastDescendant)
  const findLastDescendantIdx = (arr: WbsRow[], parentIdx: number): number => {
    const parentDepth = arr[parentIdx].depth;
    let last = parentIdx;
    for (let i = parentIdx + 1; i < arr.length; i++) {
      if (arr[i].depth > parentDepth) last = i;
      else break;
    }
    return last;
  };

  // 추가 (wace addRow): 선택된 행 다음에 같은 depth 행 추가. 선택 없으면 끝에 depth=1.
  const handleAddRow = () => {
    setRows((prev) => {
      const arr = prev.map((r) => ({ ...r, checked: false }));
      const selectedIdx = prev.map((r, i) => (r.checked ? i : -1)).filter((i) => i >= 0).pop();
      let insertAt: number;
      let depth: number;
      if (selectedIdx !== undefined && selectedIdx >= 0) {
        const sel = prev[selectedIdx];
        depth = sel.depth === 0 ? 1 : sel.depth;
        insertAt = findLastDescendantIdx(prev, selectedIdx) + 1;
      } else {
        depth = 1;
        insertAt = arr.length;
      }
      const newRow: WbsRow = { objid: newObjId(), depth, unitNo: "", taskName: "", checked: false };
      const next = [...arr.slice(0, insertAt), newRow, ...arr.slice(insertAt)];
      return renumberRows(next);
    });
  };

  // 하위추가 (wace addChildRow): depth+1 행 추가 (3 거부)
  const handleAddChildRow = () => {
    const selectedIdx = rows.map((r, i) => (r.checked ? i : -1)).filter((i) => i >= 0).pop();
    if (selectedIdx === undefined || selectedIdx < 0) {
      toast.error("부모 행을 선택해 주세요.");
      return;
    }
    const sel = rows[selectedIdx];
    if (sel.depth >= 3) {
      toast.error("수준 3 이하로는 추가할 수 없습니다.");
      return;
    }
    setRows((prev) => {
      const arr = prev.map((r) => ({ ...r, checked: false }));
      const insertAt = findLastDescendantIdx(prev, selectedIdx) + 1;
      const newRow: WbsRow = { objid: newObjId(), depth: sel.depth + 1, unitNo: "", taskName: "", checked: false };
      const next = [...arr.slice(0, insertAt), newRow, ...arr.slice(insertAt)];
      return renumberRows(next);
    });
  };

  // 삭제 (wace deleteRow): 선택 행 + 모든 후손 cascade
  const handleDeleteRow = () => {
    const checkedIdx = rows.map((r, i) => (r.checked ? i : -1)).filter((i) => i >= 0);
    if (checkedIdx.length === 0) {
      toast.error("삭제할 행을 선택해 주세요.");
      return;
    }
    const removeSet = new Set<number>();
    let hasChildren = false;
    for (const idx of checkedIdx) {
      if (rows[idx].depth === 0) continue; // TOTAL 보호
      removeSet.add(idx);
      const lastDesc = findLastDescendantIdx(rows, idx);
      if (lastDesc > idx) {
        hasChildren = true;
        for (let j = idx + 1; j <= lastDesc; j++) removeSet.add(j);
      }
    }
    const msg = hasChildren ? "하위 항목도 함께 삭제됩니다. 삭제하시겠습니까?" : "삭제하시겠습니까?";
    if (!confirm(msg)) return;
    setRows((prev) => renumberRows(prev.filter((_, i) => !removeSet.has(i))));
  };

  // 체크박스 토글
  const toggleCheck = (idx: number, val: boolean) => {
    setRows((prev) => prev.map((r, i) => (i === idx ? { ...r, checked: val } : r)));
  };

  // taskName 수정
  const updateTaskName = (idx: number, name: string) => {
    setRows((prev) => prev.map((r, i) => (i === idx ? { ...r, taskName: name } : r)));
  };

  // ─── 엑셀 임포트 (wace parsingExcelFile 1:1) ────────────

  const handleExcelFile = async (file: File) => {
    setLoading(true);
    try {
      const parsed = await wbsTemplateApi.parseExcel(file);
      // 결과를 행으로 변환 (depth는 unit_no의 '.' 개수+1)
      const total = makeTotalRow();
      const newRows: WbsRow[] = parsed.map((p) => {
        const dotCount = (p.UNIT_NO.match(/\./g) || []).length;
        const depth = Math.max(1, Math.min(3, dotCount + 1));
        return { objid: newObjId(), depth, unitNo: "", taskName: p.TASK_NAME, checked: false };
      });
      setRows(renumberRows([total, ...newRows]));
      toast.success(`${newRows.length}건 임포트 완료`);
    } catch (e: any) {
      toast.error(e?.response?.data?.message ?? e?.message ?? "엑셀 파싱 실패");
    } finally {
      setLoading(false);
    }
  };

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      if (!confirm("파일을 업로드하시겠습니까?\n기존에 입력된 항목은 삭제됩니다.")) {
        e.target.value = "";
        return;
      }
      handleExcelFile(file);
    }
    e.target.value = "";
  };

  // ─── 저장 (wace saveWBS 1:1) ──────────────────────────

  const handleSave = async () => {
    if (!product) { toast.error("제품구분을 선택해 주세요."); return; }
    if (!title.trim()) { toast.error("제목을 입력해 주세요."); return; }
    const dataRows = rows.filter((r) => r.depth > 0);
    if (dataRows.length === 0) { toast.error("등록할 항목을 추가해 주세요."); return; }
    for (const r of dataRows) {
      if (!r.unitNo || !r.taskName.trim()) {
        toast.error("수준과 Unit Name / 공정을 모두 입력해 주세요.");
        return;
      }
    }

    // 신규 모드: 중복 체크
    if (!isEditMode) {
      const dup = await wbsTemplateApi.checkDuplicate(product, title.trim());
      if (dup) {
        toast.error("이미 해당 제목으로 등록된 정보가 존재합니다.");
        return;
      }
    }

    // wace calculateParentRelations 1:1
    const totalIdx = rows.findIndex((r) => r.depth === 0);
    const totalObjId = totalIdx >= 0 ? rows[totalIdx].objid : "";
    const tasks: WbsTaskInput[] = rows.map((r, i) => {
      let upper = "";
      if (r.depth === 0) {
        upper = "";
      } else if (r.depth === 1) {
        upper = totalObjId;
      } else {
        for (let j = i - 1; j >= 0; j--) {
          if (rows[j].depth === r.depth - 1) { upper = rows[j].objid; break; }
        }
      }
      return {
        WBS_TASK_OBJID: r.objid,
        TASK_NAME: r.depth === 0 ? "TOTAL" : r.taskName,
        UNIT_NO: r.depth === 0 ? "0" : r.unitNo,
        UPPER_TASK_OBJID: upper,
        TASK_LEVEL: String(r.depth),
      };
    });

    if (!confirm("저장하시겠습니까?")) return;
    setSaving(true);
    try {
      await wbsTemplateApi.save({
        templateObjId: templateObjId ?? undefined,
        product,
        title: title.trim(),
        tasks,
      });
      toast.success("저장하였습니다.");
      onSaved();
      onOpenChange(false);
    } catch (e: any) {
      toast.error(e?.response?.data?.message ?? e?.message ?? "저장 실패");
    } finally {
      setSaving(false);
    }
  };

  const titleText = useMemo(() => (isEditMode ? "WBS 템플릿 수정" : "WBS 템플릿 등록"), [isEditMode]);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-[1340px] w-[95vw] max-h-[90vh] flex flex-col">
        <DialogHeader>
          <DialogTitle>{titleText}</DialogTitle>
        </DialogHeader>

        {/* 헤더 — 제품구분 + 제목 (수정 시 disabled) */}
        <div className="grid grid-cols-2 gap-4 px-1 py-2 border-b">
          <div>
            <Label className="mb-1 block text-xs text-muted-foreground">제품구분</Label>
            <CommCodeSelect
              groupId={PRODUCT_GROUP}
              value={product}
              onValueChange={setProduct}
              disabled={isEditMode}
            />
          </div>
          <div>
            <Label className="mb-1 block text-xs text-muted-foreground">제목</Label>
            <Input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              disabled={isEditMode}
              placeholder="템플릿 제목"
            />
          </div>
        </div>

        {/* 액션 버튼 */}
        <div className="flex flex-wrap items-center gap-2 px-1 py-2 border-b">
          <Button variant="outline" size="sm" asChild>
            <a href={TEMPLATE_DOWNLOAD_URL} download>
              <Download className="h-4 w-4" /><span className="ml-1">Template Download</span>
            </a>
          </Button>
          <Button variant="outline" size="sm" onClick={() => fileInputRef.current?.click()} disabled={loading}>
            <Upload className="h-4 w-4" /><span className="ml-1">엑셀 임포트</span>
          </Button>
          <input
            ref={fileInputRef}
            type="file"
            accept=".xlsx,.xls"
            className="hidden"
            onChange={handleFileChange}
          />
          <div className="ml-auto flex items-center gap-2">
            <Button size="sm" onClick={handleAddRow}>
              <Plus className="h-4 w-4" /><span className="ml-1">추가</span>
            </Button>
            <Button size="sm" variant="secondary" onClick={handleAddChildRow}>
              <CornerDownRight className="h-4 w-4" /><span className="ml-1">하위추가</span>
            </Button>
            <Button size="sm" variant="destructive" onClick={handleDeleteRow}>
              <Trash2 className="h-4 w-4" /><span className="ml-1">삭제</span>
            </Button>
          </div>
        </div>

        {/* 트리 그리드 */}
        <div className="flex-1 min-h-0 overflow-auto border rounded">
          <table className="w-full text-sm border-collapse">
            <thead className="bg-muted sticky top-0">
              <tr>
                <th rowSpan={2} className="border px-2 py-1 w-[5%]">선택</th>
                <th colSpan={3} className="border px-2 py-1 w-[24%]">수준</th>
                <th rowSpan={2} className="border px-2 py-1 w-[71%]">Unit Name / 공정</th>
              </tr>
              <tr>
                <th className="border px-2 py-1 w-[8%]">1</th>
                <th className="border px-2 py-1 w-[8%]">2</th>
                <th className="border px-2 py-1 w-[8%]">3</th>
              </tr>
            </thead>
            <tbody>
              {loading && (
                <tr>
                  <td colSpan={5} className="text-center py-6">
                    <Loader2 className="h-5 w-5 animate-spin inline" /> 로딩 중...
                  </td>
                </tr>
              )}
              {!loading && rows.map((r, idx) => (
                <tr key={r.objid} className={r.depth === 0 ? "bg-muted/50 font-semibold" : ""}>
                  <td className="border px-2 py-1 text-center">
                    {r.depth > 0 && (
                      <Checkbox
                        checked={r.checked}
                        onCheckedChange={(v) => toggleCheck(idx, v === true)}
                      />
                    )}
                  </td>
                  {/* 수준 1/2/3 — depth 위치에만 unitNo 표시 */}
                  <td className="border px-2 py-1 text-center">{r.depth === 1 ? r.unitNo : ""}</td>
                  <td className="border px-2 py-1 text-center">{r.depth === 2 ? r.unitNo : ""}</td>
                  <td className="border px-2 py-1 text-center">{r.depth === 3 ? r.unitNo : ""}</td>
                  <td className="border px-2 py-1">
                    {r.depth === 0 ? (
                      <div className="text-center">TOTAL</div>
                    ) : (
                      <Input
                        value={r.taskName}
                        onChange={(e) => updateTaskName(idx, e.target.value)}
                        className="h-7"
                      />
                    )}
                  </td>
                </tr>
              ))}
              {!loading && rows.length === 0 && (
                <tr><td colSpan={5} className="text-center py-6 text-muted-foreground">행이 없습니다.</td></tr>
              )}
            </tbody>
          </table>
        </div>

        <DialogFooter className="gap-2">
          <Button variant="outline" onClick={() => onOpenChange(false)}>닫기</Button>
          <Button onClick={handleSave} disabled={saving}>
            {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
            <span className="ml-1">저장</span>
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
