"use client";

import { useState, useCallback, useEffect, useMemo } from "react";
import { DataGrid, type GridColumn } from "@/components/grid/data-grid";
import { SearchForm, SearchField } from "@/components/layout/search-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { SearchableSelect } from "@/components/ui/searchable-select";
import { FolderCell } from "@/components/ui/folder-cell";
import * as XLSX from "xlsx";
import Swal from "sweetalert2";

type Row = Record<string, unknown>;

// 제품관리_BOM 조회 (원본: partMng/structureAscendingList.jsp)
// 고객사 → 프로젝트번호 → 유닛명 캐스케이드 + 품번/LEVEL 필터로 BOM 정전개 트리 조회
const LEVEL_COLORS = [
  "", "#fde9d9", "#daeef3", "#e4dfec", "#ebf1de", "#f2f2f2",
  "#f2dcdb", "#eeece1", "#dce6f1", "#FFFFEB", "#ffffff",
];

export default function BomListPage() {
  const [customerCd, setCustomerCd] = useState("");
  const [projectName, setProjectName] = useState("");
  const [unitCode, setUnitCode] = useState("");
  const [searchPartNo, setSearchPartNo] = useState("");
  const [searchLevel, setSearchLevel] = useState("");

  const [data, setData] = useState<Row[]>([]);
  const [maxLevel, setMaxLevel] = useState(0);
  const [loading, setLoading] = useState(false);
  // 접힌 노드: CHILD_OBJID 를 키로 사용 (해당 노드의 모든 하위 행을 숨김)
  const [collapsed, setCollapsed] = useState<Set<string>>(new Set());

  const [customers, setCustomers] = useState<{ value: string; label: string }[]>([]);
  const [projects, setProjects] = useState<{ value: string; label: string }[]>([]);
  const [units, setUnits] = useState<{ value: string; label: string }[]>([]);

  // 고객사 로드
  useEffect(() => {
    fetch("/api/common/supply-list", {
      method: "POST", headers: { "Content-Type": "application/json" }, body: "{}",
    }).then((r) => r.json())
      .then((j) => setCustomers((j.RESULTLIST || []).map((r: Row) => ({
        value: String(r.OBJID), label: String(r.SUPPLY_NAME || r.OBJID),
      }))))
      .catch(() => {});
  }, []);

  // 고객사 변경 → 프로젝트
  useEffect(() => {
    setProjectName(""); setUnitCode("");
    fetch("/api/common/project-list", {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ customer_cd: customerCd }),
    }).then((r) => r.json())
      .then((j) => setProjects((j.RESULTLIST || []).map((r: Row) => ({
        value: String(r.OBJID), label: String(r.LABEL || r.PROJECT_NO || r.OBJID),
      }))))
      .catch(() => {});
  }, [customerCd]);

  // 프로젝트 변경 → 유닛
  useEffect(() => {
    setUnitCode("");
    if (!projectName) { setUnits([]); return; }
    fetch("/api/common/unit-list", {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ contract_objid: projectName }),
    }).then((r) => r.json())
      .then((j) => setUnits((j.RESULTLIST || []).map((r: Row) => ({
        value: String(r.OBJID), label: String(r.UNIT_NAME || r.TASK_NAME),
      }))))
      .catch(() => {});
  }, [projectName]);

  const openPartDetail = (partObjId: string) => {
    const w = 600, h = 700;
    const left = (window.screen.width - w) / 2;
    const top = (window.screen.height - h) / 2;
    window.open(`/product/popup/part-form?objId=${encodeURIComponent(partObjId)}&readOnly=true`,
      "partMngDetail", `width=${w},height=${h},left=${left},top=${top},scrollbars=yes,resizable=yes`);
  };

  const openFilePopup = (objId: string, docType: string, docTypeName: string) => {
    const w = 800, h = 335;
    const left = (window.screen.width - w) / 2;
    const top = (window.screen.height - h) / 2;
    window.open(
      `/common/files?targetObjId=${encodeURIComponent(objId)}&docType=${encodeURIComponent(docType)}&docTypeName=${encodeURIComponent(docTypeName)}`,
      "fileRegistPopUp", `width=${w},height=${h},left=${left},top=${top}`,
    );
  };

  // 조상 체인 계산용 인덱스 (CHILD_OBJID → data index)
  const indexByChildObjid = useMemo(() => {
    const m = new Map<string, number>();
    data.forEach((r, i) => m.set(String(r.CHILD_OBJID), i));
    return m;
  }, [data]);

  // 각 row 의 조상 CHILD_OBJID 리스트 (루트→자신 바로 위)
  const ancestorsOf = useCallback((row: Row): string[] => {
    const chain: string[] = [];
    let cur: Row | undefined = row;
    while (cur && cur.PARENT_OBJID) {
      const p = String(cur.PARENT_OBJID);
      chain.push(p);
      const idx = indexByChildObjid.get(p);
      cur = idx !== undefined ? data[idx] : undefined;
    }
    return chain;
  }, [data, indexByChildObjid]);

  // 접힌 조상이 하나라도 있으면 숨김
  const visibleData = useMemo(
    () => (collapsed.size === 0
      ? data
      : data.filter((r) => !ancestorsOf(r).some((a) => collapsed.has(a)))),
    [data, collapsed, ancestorsOf],
  );

  const toggleNode = useCallback((childObjid: string) => {
    setCollapsed((prev) => {
      const next = new Set(prev);
      if (next.has(childObjid)) next.delete(childObjid);
      else next.add(childObjid);
      return next;
    });
  }, []);

  const expandAll = () => setCollapsed(new Set());
  const collapseAllLevel1 = () => {
    // LEV 1 중 자식이 있는 노드만 접기 (원본 JSP 기본 동작 상응)
    const ids = new Set<string>();
    data.forEach((r) => {
      if (Number(r.LEV ?? 0) === 1 && Number(r.LEAF ?? 1) === 0) {
        ids.add(String(r.CHILD_OBJID));
      }
    });
    setCollapsed(ids);
  };

  // 레벨 컬럼 동적 생성 (1, 2, 3 ... MAX_LEVEL)
  const levelColumns: GridColumn[] = Array.from({ length: Math.max(maxLevel, 1) }, (_, i) => ({
    title: String(i + 1), field: `_LEV_${i + 1}`, width: 22, hozAlign: "center",
    formatter: (_cell, row) => Number(row.LEV ?? 0) === i + 1 ? "*" : "",
  }));

  const columns: GridColumn[] = [
    {
      title: "", field: "_TREE", width: 28, hozAlign: "center",
      formatter: (_cell, row) => {
        if (Number(row.LEAF ?? 1) !== 0) return "";
        const id = String(row.CHILD_OBJID);
        const isCollapsed = collapsed.has(id);
        return (
          <button
            type="button"
            onClick={(e) => { e.stopPropagation(); toggleNode(id); }}
            className="inline-flex h-4 w-4 items-center justify-center border border-gray-400 text-[11px] leading-none font-bold text-gray-700 hover:bg-gray-100"
            aria-label={isCollapsed ? "펴기" : "접기"}
          >
            {isCollapsed ? "+" : "−"}
          </button>
        );
      },
    },
    ...levelColumns,
    {
      title: "품번", field: "PART_NO", width: 140, hozAlign: "left",
      cellClick: (row) => openPartDetail(String(row.PART_OBJID)),
    },
    { title: "품명", field: "PART_NAME", width: 180, hozAlign: "left" },
    { title: "수량", field: "QTY", width: 55, hozAlign: "center" },
    {
      title: "3D", field: "FILE_3D_CNT", width: 40, hozAlign: "center",
      formatter: (cell) => <FolderCell count={cell} />,
      cellClick: (row) => openFilePopup(String(row.PART_OBJID), "3D_CAD", "3D CAD 첨부파일"),
    },
    {
      title: "2D", field: "FILE_2D_CNT", width: 40, hozAlign: "center",
      formatter: (cell) => <FolderCell count={cell} />,
      cellClick: (row) => openFilePopup(String(row.PART_OBJID), "2D_DRAWING_CAD", "2D(Drawing) CAD 첨부파일"),
    },
    {
      title: "PDF", field: "FILE_PDF_CNT", width: 40, hozAlign: "center",
      formatter: (cell) => <FolderCell count={cell} />,
      cellClick: (row) => openFilePopup(String(row.PART_OBJID), "2D_PDF_CAD", "2D(PDF) CAD 첨부파일"),
    },
    { title: "재질", field: "MATERIAL", width: 100, hozAlign: "left" },
    { title: "사양(규격)", field: "SPEC", width: 130, hozAlign: "left" },
    { title: "후처리", field: "POST_PROCESSING", width: 120, hozAlign: "left" },
    { title: "MAKER", field: "MAKER", width: 90, hozAlign: "left" },
    { title: "Revision", field: "REVISION", width: 70, hozAlign: "center" },
    { title: "EO No", field: "EO_NO", width: 85, hozAlign: "center" },
    { title: "EO Date", field: "EO_DATE", width: 90, hozAlign: "center" },
    { title: "PART구분", field: "PART_TYPE_TITLE", width: 90, hozAlign: "center" },
    { title: "비고", field: "REMARK", width: 200, hozAlign: "left" },
  ];

  const validate = () => {
    // 품번만 입력해도 검색 허용 — 품번이 있으면 고객사/프로젝트/유닛 미선택 가능
    if (searchPartNo) return true;
    if (!customerCd) { Swal.fire("알림", "고객사를 선택하거나 품번을 입력해 주세요.", "warning"); return false; }
    if (!projectName) { Swal.fire("알림", "프로젝트번호를 선택해 주세요.", "warning"); return false; }
    if (!unitCode) { Swal.fire("알림", "유닛명을 선택해 주세요.", "warning"); return false; }
    return true;
  };

  const fetchData = useCallback(async (skipValidate = false) => {
    if (!skipValidate && !validate()) return;
    if (!searchPartNo && (!customerCd || !projectName || !unitCode)) return;
    setLoading(true);
    try {
      const res = await fetch("/api/product/bom/ascending", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          customer_cd: customerCd,
          project_name: projectName,
          unit_code: unitCode,
          search_partNo: searchPartNo,
          search_level: searchLevel,
        }),
      });
      if (res.ok) {
        const j = await res.json();
        setData(j.RESULTLIST || []);
        setMaxLevel(Number(j.MAX_LEVEL || 0));
        setCollapsed(new Set());
      }
    } finally {
      setLoading(false);
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [customerCd, projectName, unitCode, searchPartNo, searchLevel]);

  const handleReset = () => {
    setCustomerCd(""); setProjectName(""); setUnitCode("");
    setSearchPartNo(""); setSearchLevel("");
    setData([]); setMaxLevel(0);
    setCollapsed(new Set());
  };

  const handleExcel = () => {
    if (data.length === 0) { Swal.fire("알림", "다운로드할 데이터가 없습니다.", "warning"); return; }
    const levelHeaders = Array.from({ length: Math.max(maxLevel, 1) }, (_, i) => String(i + 1));
    const header = [
      ...levelHeaders, "품번", "품명", "수량", "3D", "2D", "PDF",
      "재질", "사양(규격)", "후처리", "MAKER", "Revision",
      "EO No", "EO Date", "PART구분", "비고",
    ];
    const body = data.map((r) => {
      const lev = Number(r.LEV ?? 0);
      const markers = Array.from({ length: Math.max(maxLevel, 1) }, (_, i) => (lev === i + 1 ? "*" : ""));
      return [
        ...markers, r.PART_NO ?? "", r.PART_NAME ?? "", r.QTY ?? "",
        Number(r.FILE_3D_CNT ?? 0), Number(r.FILE_2D_CNT ?? 0), Number(r.FILE_PDF_CNT ?? 0),
        r.MATERIAL ?? "", r.SPEC ?? "", r.POST_PROCESSING ?? "",
        r.MAKER ?? "", r.REVISION ?? "", r.EO_NO ?? "",
        r.EO_DATE ?? "", r.PART_TYPE_TITLE ?? "", r.REMARK ?? "",
      ];
    });
    const ws = XLSX.utils.aoa_to_sheet([header, ...body]);
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "BOM_REPORT_정전개");
    const today = new Date().toISOString().slice(0, 10);
    XLSX.writeFile(wb, `BOM_REPORT_정전개_${today}.xlsx`);
  };

  // 행별 배경색(레벨별)
  const rowClass = (row: Row): string => {
    const lev = Number(row.LEV ?? 0);
    const bg = LEVEL_COLORS[Math.min(lev, LEVEL_COLORS.length - 1)];
    return bg ? "" : "";
    void bg; // 배경색은 인라인 스타일 쓰지 않고 기본 유지 (선택적)
  };
  void rowClass;

  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-lg font-bold text-gray-800">제품관리_BOM 조회</h2>
        <div className="flex gap-2">
          <Button size="sm" variant="secondary" onClick={expandAll} disabled={data.length === 0}>전체 펴기</Button>
          <Button size="sm" variant="secondary" onClick={collapseAllLevel1} disabled={data.length === 0}>전체 접기</Button>
          <Button size="sm" onClick={() => fetchData()}>조회</Button>
          <Button size="sm" variant="secondary" onClick={handleReset}>초기화</Button>
          <Button size="sm" variant="secondary" onClick={handleExcel}>Excel Download</Button>
        </div>
      </div>

      <SearchForm onSearch={() => fetchData()}>
        <SearchField label="고객사 *">
          <SearchableSelect options={customers} value={customerCd} onChange={setCustomerCd} className="w-[180px]" />
        </SearchField>
        <SearchField label="프로젝트번호 *">
          <SearchableSelect options={projects} value={projectName} onChange={setProjectName} className="w-[220px]" />
        </SearchField>
        <SearchField label="유닛명 *">
          <SearchableSelect options={units} value={unitCode} onChange={setUnitCode} className="w-[300px]" />
        </SearchField>
        <SearchField label="품번">
          <Input value={searchPartNo} onChange={(e) => setSearchPartNo(e.target.value)} className="w-[200px]" />
        </SearchField>
        <SearchField label="LEVEL">
          <select value={searchLevel} onChange={(e) => setSearchLevel(e.target.value)}
            className="h-9 w-[80px] rounded border border-gray-300 bg-white px-2 text-sm">
            <option value="">전체</option>
            {[1, 2, 3, 4, 5, 6].map((n) => <option key={n} value={n}>{n}</option>)}
          </select>
        </SearchField>
      </SearchForm>

      <DataGrid columns={columns} data={visibleData} loading={loading} />
    </div>
  );
}
