"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Loader2,
  Settings,
  Plus,
  Pencil,
  Trash2,
  Search,
  RotateCcw,
  Wrench,
  Upload,
} from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  ResizablePanelGroup,
  ResizablePanel,
  ResizableHandle,
} from "@/components/ui/resizable";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { EDataTable, EDataTableColumn } from "@/components/common/EDataTable";
import { SmartSelect } from "@/components/common/SmartSelect";
import {
  getProcessList,
  createProcess,
  updateProcess,
  deleteProcesses,
  getProcessEquipments,
  addProcessEquipment,
  removeProcessEquipment,
  getEquipmentList,
  type ProcessMaster,
  type ProcessEquipment,
  type Equipment,
} from "@/lib/api/processInfo"; // API: /process-info/*
import { getCategoryValues } from "@/lib/api/tableCategoryValue";
import { SmartExcelUploadModal } from "@/components/common/SmartExcelUpload";
import type { SmartExcelUploadConfig, ParsedSheetData } from "@/components/common/SmartExcelUpload";
import { allocateNumberingCode } from "@/lib/api/numberingRule";
import { apiClient } from "@/lib/api/client";

const ALL_VALUE = "__all__";

export function ProcessMasterTab() {
  const [processes, setProcesses] = useState<ProcessMaster[]>([]);
  const [equipmentMaster, setEquipmentMaster] = useState<Equipment[]>([]);
  const [processTypeOptions, setProcessTypeOptions] = useState<{ valueCode: string; valueLabel: string }[]>([]);
  const [useYnOptions, setUseYnOptions] = useState<{ valueCode: string; valueLabel: string }[]>([]);
  const [excelOpen, setExcelOpen] = useState(false);
  const [loadingInitial, setLoadingInitial] = useState(true);
  const [loadingList, setLoadingList] = useState(false);
  const [loadingEquipments, setLoadingEquipments] = useState(false);

  const [filterCode, setFilterCode] = useState("");
  const [filterName, setFilterName] = useState("");
  const [filterType, setFilterType] = useState<string>(ALL_VALUE);
  const [filterUseYn, setFilterUseYn] = useState<string>(ALL_VALUE);

  const [selectedProcess, setSelectedProcess] = useState<ProcessMaster | null>(null);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set());

  const [processEquipments, setProcessEquipments] = useState<ProcessEquipment[]>([]);
  const [equipmentPick, setEquipmentPick] = useState<string>("");
  const [addingEquipment, setAddingEquipment] = useState(false);

  const [formOpen, setFormOpen] = useState(false);
  const [formMode, setFormMode] = useState<"add" | "edit">("add");
  const [savingForm, setSavingForm] = useState(false);
  const [formProcessCode, setFormProcessCode] = useState("");
  const [formProcessName, setFormProcessName] = useState("");
  const [formProcessType, setFormProcessType] = useState<string>("");
  const [formStandardTime, setFormStandardTime] = useState("");
  const [formWorkerCount, setFormWorkerCount] = useState("");
  const [formUseYn, setFormUseYn] = useState("");
  const [editingId, setEditingId] = useState<string | null>(null);

  const [deleteOpen, setDeleteOpen] = useState(false);
  const [deleting, setDeleting] = useState(false);

  const processTypeMap = useMemo(() => {
    const m = new Map<string, string>();
    processTypeOptions.forEach((o) => m.set(o.valueCode, o.valueLabel));
    return m;
  }, [processTypeOptions]);

  const getProcessTypeLabel = useCallback(
    (code: string) => processTypeMap.get(code) ?? code,
    [processTypeMap]
  );

  const loadProcesses = useCallback(async () => {
    setLoadingList(true);
    try {
      const res = await getProcessList({
        processCode: filterCode.trim() || undefined,
        processName: filterName.trim() || undefined,
        processType: filterType === ALL_VALUE ? undefined : filterType,
        useYn: filterUseYn === ALL_VALUE ? undefined : filterUseYn,
      });
      if (!res.success) {
        toast.error(res.message || "공정 목록을 불러오지 못했어요");
        return;
      }
      setProcesses(res.data ?? []);
    } finally {
      setLoadingList(false);
    }
  }, [filterCode, filterName, filterType, filterUseYn]);

  const loadInitial = useCallback(async () => {
    setLoadingInitial(true);
    try {
      const [procRes, eqRes] = await Promise.all([getProcessList(), getEquipmentList()]);
      if (!procRes.success) {
        toast.error(procRes.message || "공정 목록을 불러오지 못했어요");
      } else {
        setProcesses(procRes.data ?? []);
      }
      if (!eqRes.success) {
        toast.error(eqRes.message || "설비 목록을 불러오지 못했어요");
      } else {
        setEquipmentMaster(eqRes.data ?? []);
      }
      const ptRes = await getCategoryValues("process_mng", "process_type");
      if (ptRes.success && "data" in ptRes && Array.isArray(ptRes.data)) {
        const activeValues = ptRes.data.filter((v: any) => v.isActive !== false);
        const seen = new Set<string>();
        const unique = activeValues.filter((v: any) => {
          if (seen.has(v.valueCode)) return false;
          seen.add(v.valueCode);
          return true;
        });
        setProcessTypeOptions(unique.map((v: any) => ({ valueCode: v.valueCode, valueLabel: v.valueLabel })));
      }
      // 사용여부 카테고리 (엑셀업로드 드롭다운용)
      const uyRes = await getCategoryValues("process_mng", "use_yn");
      if (uyRes.success && "data" in uyRes && Array.isArray(uyRes.data)) {
        const activeValues = uyRes.data.filter((v: any) => v.isActive !== false);
        const seen = new Set<string>();
        const unique = activeValues.filter((v: any) => {
          if (seen.has(v.valueCode)) return false;
          seen.add(v.valueCode);
          return true;
        });
        setUseYnOptions(unique.map((v: any) => ({ valueCode: v.valueCode, valueLabel: v.valueLabel })));
      }
    } finally {
      setLoadingInitial(false);
    }
  }, []);

  useEffect(() => {
    void loadInitial();
  }, [loadInitial]);

  useEffect(() => {
    setSelectedProcess((prev) => {
      if (!prev) return prev;
      if (!processes.some((p) => p.id === prev.id)) return null;
      return prev;
    });
  }, [processes]);

  useEffect(() => {
    setEquipmentPick("");
  }, [selectedProcess?.id]);

  useEffect(() => {
    if (!selectedProcess) {
      setProcessEquipments([]);
      return;
    }
    let cancelled = false;
    setLoadingEquipments(true);
    void (async () => {
      const res = await getProcessEquipments(selectedProcess.process_code);
      if (cancelled) return;
      if (!res.success) {
        toast.error(res.message || "공정 설비를 불러오지 못했어요");
        setProcessEquipments([]);
      } else {
        setProcessEquipments(res.data ?? []);
      }
      setLoadingEquipments(false);
    })();
    return () => {
      cancelled = true;
    };
  }, [selectedProcess?.process_code]);

  const handleResetFilters = () => {
    setFilterCode("");
    setFilterName("");
    setFilterType(ALL_VALUE);
    setFilterUseYn(ALL_VALUE);
  };

  const handleSearch = () => {
    void loadProcesses();
  };

  const openAdd = () => {
    setFormMode("add");
    setEditingId(null);
    setFormProcessCode("");
    setFormProcessName("");
    setFormProcessType(processTypeOptions[0]?.valueCode ?? "");
    setFormStandardTime("");
    setFormWorkerCount("");
    setFormUseYn("Y");
    setFormOpen(true);
  };

  const openEdit = () => {
    if (selectedIds.size === 0) {
      toast.message("수정할 공정을 체크박스로 선택해주세요");
      return;
    }
    if (selectedIds.size > 1) {
      toast.message("수정은 1건만 선택해주세요");
      return;
    }
    const targetId = Array.from(selectedIds)[0];
    const target = processes.find((p) => p.id === targetId);
    if (!target) {
      toast.error("선택한 공정을 찾을 수 없습니다");
      return;
    }
    setFormMode("edit");
    setEditingId(target.id);
    setFormProcessCode(target.process_code);
    setFormProcessName(target.process_name);
    setFormProcessType(target.process_type);
    setFormStandardTime(target.standard_time ?? "");
    setFormWorkerCount(target.worker_count ?? "");
    setFormUseYn(target.use_yn);
    setFormOpen(true);
  };

  const submitForm = async () => {
    if (!formProcessName.trim()) {
      toast.error("공정명을 입력해주세요");
      return;
    }

    setSavingForm(true);
    try {
      if (formMode === "add") {
        const res = await createProcess({
          process_name: formProcessName.trim(),
          process_type: formProcessType,
          standard_time: formStandardTime.trim() || "0",
          worker_count: formWorkerCount.trim() || "0",
          use_yn: formUseYn,
        });
        if (!res.success || !res.data) {
          toast.error(res.message || "등록에 실패했어요");
          return;
        }
        toast.success("공정이 등록되었어요");
        setFormOpen(false);
        await loadProcesses();
        setSelectedProcess(res.data);
        setSelectedIds(new Set());
      } else if (editingId) {
        const res = await updateProcess(editingId, {
          process_name: formProcessName.trim(),
          process_type: formProcessType,
          standard_time: formStandardTime.trim() || "0",
          worker_count: formWorkerCount.trim() || "0",
          use_yn: formUseYn,
        });
        if (!res.success || !res.data) {
          toast.error(res.message || "수정에 실패했어요");
          return;
        }
        toast.success("공정이 수정되었어요");
        setFormOpen(false);
        await loadProcesses();
        setSelectedProcess(res.data);
      }
    } finally {
      setSavingForm(false);
    }
  };

  const openDelete = () => {
    if (selectedIds.size === 0) {
      toast.message("삭제할 공정을 체크박스로 선택해주세요");
      return;
    }
    setDeleteOpen(true);
  };

  const confirmDelete = async () => {
    const ids = Array.from(selectedIds);
    setDeleting(true);
    try {
      const res = await deleteProcesses(ids);
      if (!res.success) {
        toast.error(res.message || "삭제에 실패했어요");
        return;
      }
      toast.success(`${ids.length}건 삭제되었어요`);
      setDeleteOpen(false);
      setSelectedIds(new Set());
      if (selectedProcess && ids.includes(selectedProcess.id)) {
        setSelectedProcess(null);
      }
      await loadProcesses();
    } finally {
      setDeleting(false);
    }
  };

  const availableEquipments = useMemo(() => {
    // equipment_code 컬럼에 code(legacy) 또는 id(신규)가 들어있을 수 있음
    // 빈 값은 used set에서 제외 (코드 없는 설비를 모두 가리는 것 방지)
    const used = new Set<string>();
    for (const pe of processEquipments) {
      if (pe.equipment_code) used.add(pe.equipment_code);
    }
    return equipmentMaster.filter((e) => {
      if (e.equipment_code && used.has(e.equipment_code)) return false;
      if (e.id && used.has(e.id)) return false;
      return true;
    });
  }, [equipmentMaster, processEquipments]);

  const handleAddEquipment = async () => {
    if (!selectedProcess) return;
    if (!equipmentPick) {
      toast.message("추가할 설비를 선택해주세요");
      return;
    }
    const picked = availableEquipments.find((e) => e.id === equipmentPick);
    if (!picked) {
      toast.error("선택한 설비를 찾을 수 없어요");
      return;
    }
    setAddingEquipment(true);
    try {
      // equipment_code가 비어있으면 id를 저장 (백엔드 JOIN이 양쪽 다 매칭)
      const res = await addProcessEquipment({
        process_code: selectedProcess.process_code,
        equipment_code: picked.equipment_code || picked.id,
      });
      if (!res.success) {
        toast.error(res.message || "설비 추가에 실패했어요");
        return;
      }
      toast.success("설비가 등록되었어요");
      setEquipmentPick("");
      const listRes = await getProcessEquipments(selectedProcess.process_code);
      if (listRes.success && listRes.data) setProcessEquipments(listRes.data);
    } finally {
      setAddingEquipment(false);
    }
  };

  const handleRemoveEquipment = async (row: ProcessEquipment) => {
    const res = await removeProcessEquipment(row.id);
    if (!res.success) {
      toast.error(res.message || "설비 제거에 실패했어요");
      return;
    }
    toast.success("설비가 제거되었어요");
    if (selectedProcess) {
      const listRes = await getProcessEquipments(selectedProcess.process_code);
      if (listRes.success && listRes.data) setProcessEquipments(listRes.data);
    }
  };

  const listBusy = loadingInitial || loadingList;

  /* ═══════════════════ 엑셀 업로드 설정 ═══════════════════ */
  const processTypeLabelToCode = useMemo(() => {
    const m: Record<string, string> = {};
    processTypeOptions.forEach((o) => {
      m[o.valueLabel] = o.valueCode;
    });
    return m;
  }, [processTypeOptions]);

  const useYnLabelToCode = useMemo(() => {
    const m: Record<string, string> = {};
    useYnOptions.forEach((o) => {
      m[o.valueLabel] = o.valueCode;
    });
    return m;
  }, [useYnOptions]);

  const excelConfig = useMemo<SmartExcelUploadConfig>(
    () => ({
      templateName: "공정 마스터",
      sheets: [
        {
          name: "공정 마스터",
          typeKey: "process_mng",
          columns: [
            { key: "process_code", label: "공정코드", type: "text", width: 14 },
            { key: "process_name", label: "공정명", required: true, type: "text", width: 20 },
            {
              key: "process_type",
              label: "공정유형",
              required: true,
              type: "dropdown",
              dropdown: { source: "custom", values: processTypeOptions.map((o) => o.valueLabel) },
              width: 18,
            },
            { key: "standard_time", label: "표준시간(분)", type: "number", width: 12 },
            { key: "worker_count", label: "작업인원", type: "number", width: 10 },
            {
              key: "use_yn",
              label: "사용여부",
              type: "dropdown",
              dropdown: { source: "custom", values: useYnOptions.map((o) => o.valueLabel) },
              width: 10,
            },
            // 설비명을 쉼표로 구분하여 입력 (예: "절단기1,포장기"). 매칭 실패한 이름은 스킵.
            { key: "equipment_list", label: "사용설비(쉼표구분)", type: "text", width: 28 },
          ],
        },
      ],
    }),
    [processTypeOptions, useYnOptions],
  );

  const excelDropdownOptions = useMemo<Record<string, string[]>>(
    () => ({
      process_type: processTypeOptions.map((o) => o.valueLabel),
      use_yn: useYnOptions.map((o) => o.valueLabel),
    }),
    [processTypeOptions, useYnOptions],
  );

  const excelLabelToCodeMap = useMemo<Record<string, Record<string, string>>>(
    () => ({
      process_type: processTypeLabelToCode,
      use_yn: useYnLabelToCode,
    }),
    [processTypeLabelToCode, useYnLabelToCode],
  );

  const handleExcelUpload = async (data: ParsedSheetData[]) => {
    const rows = data[0]?.rows ?? [];
    if (rows.length === 0) {
      toast.error("업로드할 데이터가 없어요");
      return;
    }

    // 채번 규칙 사전 조회 (공정코드 미입력 행에만 사용)
    let ruleId: string | null = null;
    try {
      const res = await apiClient.get(`/numbering-rules/by-column/process_mng/process_code`);
      if (res.data?.success && res.data?.data?.ruleId) {
        ruleId = res.data.data.ruleId;
      }
    } catch {
      /* 채번 규칙 없으면 스킵 */
    }

    let okCount = 0;
    const failList: string[] = [];

    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      try {
        // row.{key}는 templateParser가 이미 label→code로 자동변환한 값 (dropdown 컬럼)
        let processCode = String(row.process_code || "").trim();
        if (!processCode && ruleId) {
          const alloc = await allocateNumberingCode(ruleId);
          if (alloc.success && alloc.data?.generatedCode) {
            processCode = alloc.data.generatedCode;
          } else {
            failList.push(`${i + 2}행: 채번 실패`);
            continue;
          }
        }
        if (!processCode) {
          failList.push(`${i + 2}행: 공정코드 없음 (채번 규칙 필요)`);
          continue;
        }

        const payload = {
          process_code: processCode,
          process_name: row.process_name || "",
          process_type: row.process_type || "",
          standard_time: String(row.standard_time ?? ""),
          worker_count: String(row.worker_count ?? ""),
          use_yn: row.use_yn || "USE_Y",
        };

        // 기존 공정 조회 후 upsert
        const existRes = await getProcessList({ processCode });
        const existing = existRes.success
          ? (existRes.data ?? []).find((p) => p.process_code === processCode)
          : null;
        if (existing) {
          const up = await updateProcess(existing.id, payload);
          if (!up.success) {
            failList.push(`${i + 2}행: 수정 실패`);
            continue;
          }
        } else {
          const cr = await createProcess(payload);
          if (!cr.success) {
            failList.push(`${i + 2}행: 등록 실패`);
            continue;
          }
        }

        // 사용설비 매핑 (쉼표 구분 설비명). 매칭 안 되는 이름은 무시 (사용자 책임).
        const rawEqs = String(row.equipment_list || "").trim();
        if (rawEqs) {
          const eqLabels = rawEqs.split(",").map((s) => s.trim()).filter(Boolean);
          // 기존 매핑 조회 후 중복 방지
          const curRes = await getProcessEquipments(processCode);
          const currentSet = new Set((curRes.success ? curRes.data ?? [] : []).map((e) => e.equipment_code));
          const eqByName = new Map(equipmentMaster.map((e) => [e.equipment_name, e.equipment_code]));
          for (const label of eqLabels) {
            const eqCode = eqByName.get(label);
            if (!eqCode) continue; // 오타/미등록 설비 → 스킵
            if (currentSet.has(eqCode)) continue; // 이미 매핑됨
            await addProcessEquipment({ process_code: processCode, equipment_code: eqCode });
            currentSet.add(eqCode);
          }
        }

        okCount++;
      } catch {
        failList.push(`${i + 2}행: 저장 실패`);
      }
    }

    if (okCount > 0) toast.success(`${okCount}건을 업로드했어요`);
    if (failList.length > 0) {
      toast.error(
        `실패 ${failList.length}건: ${failList.slice(0, 3).join(" / ")}${failList.length > 3 ? " …" : ""}`,
      );
    }
    void loadProcesses();
  };

  // 표시용 데이터
  const processGridData = useMemo(
    () =>
      processes.map((p) => ({
        ...p,
        process_type_display: getProcessTypeLabel(p.process_type),
        use_yn_display: p.use_yn === "Y" ? "사용" : "미사용",
      })),
    [processes, getProcessTypeLabel]
  );

  return (
    <div className="flex h-full flex-col">
      <ResizablePanelGroup direction="horizontal" className="min-h-0 flex-1">
        {/* 좌측: 공정 목록 */}
        <ResizablePanel defaultSize={50} minSize={30}>
          <div className="flex h-full flex-col">
            {/* 패널 헤더 */}
            <div className="flex items-center gap-2 border-b bg-muted/30 px-4 py-2">
              <Settings className="h-4 w-4 text-muted-foreground" />
              <span className="text-sm font-semibold">공정 마스터</span>
              <Badge variant="secondary" className="font-mono text-xs">
                {processes.length}건
              </Badge>
            </div>

            {/* 필터 바 */}
            <div className="flex flex-wrap items-center gap-2 border-b px-3 py-2">
              <Input value={filterCode} onChange={(e) => setFilterCode(e.target.value)} placeholder="공정코드" className="h-8 w-[110px] text-xs" />
              <Input value={filterName} onChange={(e) => setFilterName(e.target.value)} placeholder="공정명" className="h-8 w-[130px] text-xs" />
              <Select value={filterType} onValueChange={setFilterType}>
                <SelectTrigger className="h-8 w-[110px] text-xs">
                  <SelectValue placeholder="유형 전체" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_VALUE}>전체</SelectItem>
                  {processTypeOptions.map((o, idx) => (
                    <SelectItem key={`pt-filter-${idx}`} value={o.valueCode}>{o.valueLabel}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <Select value={filterUseYn} onValueChange={setFilterUseYn}>
                <SelectTrigger className="h-8 w-[100px] text-xs">
                  <SelectValue placeholder="사용 전체" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_VALUE}>전체</SelectItem>
                  <SelectItem value="Y">사용</SelectItem>
                  <SelectItem value="N">미사용</SelectItem>
                </SelectContent>
              </Select>
              <div className="flex-1" />
              {listBusy && <Loader2 className="h-3.5 w-3.5 animate-spin text-muted-foreground" />}
              <Button size="sm" className="h-8 gap-1 text-xs" onClick={handleSearch} disabled={listBusy}>
                <Search className="h-3 w-3" />조회
              </Button>
              <Button variant="ghost" size="sm" className="h-8 gap-1 text-xs text-muted-foreground" onClick={handleResetFilters}>
                <RotateCcw className="h-3 w-3" />초기화
              </Button>
            </div>

            {/* 액션 바 */}
            <div className="flex items-center justify-end gap-2 border-b bg-muted/30 px-4 py-2">
              <Button size="sm" variant="outline" onClick={() => setExcelOpen(true)}>
                <Upload className="mr-1 h-3.5 w-3.5" />
                엑셀업로드
              </Button>
              <Button size="sm" onClick={openAdd}>
                <Plus className="mr-1 h-3.5 w-3.5" />
                공정 추가
              </Button>
              <Button variant="secondary" size="sm" onClick={openEdit}>
                <Pencil className="mr-1 h-3.5 w-3.5" />
                수정
              </Button>
              <Button variant="destructive" size="sm" onClick={openDelete}>
                <Trash2 className="mr-1 h-3.5 w-3.5" />
                삭제
              </Button>
            </div>

            {/* 공정 목록 테이블 */}
            <div className="min-h-0 flex-1 overflow-auto">
              <EDataTable
                columns={[
                  { key: "process_code", label: "공정코드", width: "w-[130px]", render: (val: any) => <span className="font-mono text-xs">{val}</span> },
                  { key: "process_name", label: "공정명" },
                  { key: "process_type_display", label: "공정유형", width: "w-[120px]" },
                  { key: "standard_time", label: "표준시간(분)", width: "w-[110px]", align: "right" as const },
                  { key: "worker_count", label: "작업인원", width: "w-[90px]", align: "right" as const },
                  { key: "use_yn_display", label: "사용여부", width: "w-[90px]", align: "center" as const },
                ] as EDataTableColumn[]}
                data={processGridData}
                rowKey={(row) => row.id}
                loading={listBusy}
                emptyMessage="조회된 공정이 없어요"
                selectedId={selectedProcess?.id ?? null}
                onSelect={(id) => {
                  const proc = processes.find((p) => p.id === id);
                  setSelectedProcess(proc || null);
                }}
                onRowClick={(row) => {
                  const proc = processes.find((p) => p.id === row.id);
                  setSelectedProcess(proc || null);
                }}
                showCheckbox
                checkedIds={Array.from(selectedIds)}
                onCheckedChange={(ids) => setSelectedIds(new Set(ids))}
                showPagination={false}
                draggableColumns={false}
              />
            </div>
          </div>
        </ResizablePanel>

        <ResizableHandle withHandle />

        {/* 우측: 공정별 설비 */}
        <ResizablePanel defaultSize={50} minSize={30}>
          <div className="flex h-full flex-col">
            {/* 패널 헤더 */}
            <div className="flex items-center gap-2 border-b bg-muted/30 px-4 py-2">
              <Wrench className="h-4 w-4 text-muted-foreground" />
              <div className="min-w-0 flex-1">
                <p className="truncate text-sm font-semibold">공정별 사용설비</p>
                {selectedProcess ? (
                  <p className="truncate text-xs text-muted-foreground">
                    {selectedProcess.process_name} ({selectedProcess.process_code})
                  </p>
                ) : (
                  <p className="text-xs text-muted-foreground">공정을 선택해주세요</p>
                )}
              </div>
            </div>

            {!selectedProcess ? (
              <div className="flex flex-1 flex-col items-center justify-center gap-2 text-center text-muted-foreground">
                <Settings className="h-10 w-10 opacity-40" />
                <p className="text-sm font-medium text-foreground">좌측에서 공정을 선택해주세요</p>
                <p className="max-w-xs text-xs">
                  목록 행을 클릭하면 이 공정에 연결된 설비를 관리할 수 있어요
                </p>
              </div>
            ) : (
              <div className="flex min-h-0 flex-1 flex-col gap-3 p-4">
                <div className="flex items-end gap-2">
                  <div className="min-w-0 flex-1 space-y-1">
                    <Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">설비 선택</Label>
                    <SmartSelect
                      key={selectedProcess.id}
                      options={availableEquipments.map((eq) => ({
                        code: eq.id,
                        label: eq.equipment_name,
                      }))}
                      value={equipmentPick || ""}
                      onValueChange={setEquipmentPick}
                      placeholder="설비를 선택해주세요"
                      disabled={addingEquipment || availableEquipments.length === 0}
                    />
                  </div>
                  <Button
                    size="sm"
                    onClick={() => void handleAddEquipment()}
                    disabled={addingEquipment || !equipmentPick}
                  >
                    {addingEquipment ? (
                      <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
                    ) : (
                      <Plus className="mr-1 h-3.5 w-3.5" />
                    )}
                    추가
                  </Button>
                </div>

                <div className="min-h-0 flex-1 overflow-auto">
                  {loadingEquipments ? (
                    <div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
                      <Loader2 className="h-7 w-7 animate-spin" />
                      <p className="mt-2 text-sm">설비 목록을 불러오고 있어요...</p>
                    </div>
                  ) : processEquipments.length === 0 ? (
                    <p className="py-8 text-center text-sm text-muted-foreground">
                      등록된 설비가 없어요. 상단에서 설비를 추가해주세요.
                    </p>
                  ) : (
                    <ul className="space-y-2">
                      {processEquipments.map((pe) => (
                        <li key={pe.id} className="flex items-center gap-3 rounded-lg border p-3 transition-colors hover:bg-muted/30">
                          <div className="min-w-0 flex-1">
                            <p className="truncate text-sm font-medium">
                              {pe.equipment_name
                                || equipmentMaster.find((e) => e.id === pe.equipment_code || e.equipment_code === pe.equipment_code)?.equipment_name
                                || "설비명 없음"}
                            </p>
                          </div>
                          <Button variant="ghost" size="sm" onClick={() => void handleRemoveEquipment(pe)}>
                            <Trash2 className="mr-1 h-3.5 w-3.5" />
                            제거
                          </Button>
                        </li>
                      ))}
                    </ul>
                  )}
                </div>
              </div>
            )}
          </div>
        </ResizablePanel>
      </ResizablePanelGroup>

      {/* 공정 등록/수정 모달 */}
      <Dialog open={formOpen} onOpenChange={setFormOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>{formMode === "add" ? "공정 추가" : "공정 수정"}</DialogTitle>
            <DialogDescription>공정 마스터 정보를 입력해주세요</DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-1">
              <Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
                공정명 <span className="text-destructive">*</span>
              </Label>
              <Input
                value={formProcessName}
                onChange={(e) => setFormProcessName(e.target.value)}
                placeholder="공정명을 입력해주세요"
                className="h-9"
              />
            </div>
            <div className="space-y-1">
              <Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">공정유형</Label>
              <Select value={formProcessType} onValueChange={setFormProcessType}>
                <SelectTrigger className="h-9" size="sm">
                  <SelectValue placeholder="선택해주세요" />
                </SelectTrigger>
                <SelectContent>
                  {processTypeOptions.map((o, idx) => (
                    <SelectItem key={`pt-form-${idx}`} value={o.valueCode}>{o.valueLabel}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1">
              <Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">표준작업시간(분)</Label>
              <Input
                value={formStandardTime}
                onChange={(e) => setFormStandardTime(e.target.value)}
                placeholder="0"
                inputMode="numeric"
                className="h-9"
              />
            </div>
            <div className="space-y-1">
              <Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">작업인원수</Label>
              <Input
                value={formWorkerCount}
                onChange={(e) => setFormWorkerCount(e.target.value)}
                placeholder="0"
                inputMode="numeric"
                className="h-9"
              />
            </div>
            <div className="space-y-1">
              <Label className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">사용여부</Label>
              <Select value={formUseYn} onValueChange={setFormUseYn}>
                <SelectTrigger className="h-9" size="sm">
                  <SelectValue placeholder="선택해주세요" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="Y">사용</SelectItem>
                  <SelectItem value="N">미사용</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setFormOpen(false)} disabled={savingForm}>취소</Button>
            <Button onClick={() => void submitForm()} disabled={savingForm}>
              {savingForm && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
              저장해요
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 삭제 확인 */}
      <Dialog open={deleteOpen} onOpenChange={setDeleteOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>공정 삭제</DialogTitle>
            <DialogDescription>
              선택한 {selectedIds.size}건의 공정을 삭제해요. 연결된 공정-설비 매핑도 함께 삭제돼요. 이 작업은 되돌릴 수 없어요.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="gap-2">
            <Button variant="outline" onClick={() => setDeleteOpen(false)} disabled={deleting}>취소</Button>
            <Button variant="destructive" onClick={() => void confirmDelete()} disabled={deleting}>
              {deleting && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
              삭제해요
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* ═══════════════════ 엑셀업로드 모달 ═══════════════════ */}
      <SmartExcelUploadModal
        open={excelOpen}
        onOpenChange={setExcelOpen}
        config={excelConfig}
        dropdownOptions={excelDropdownOptions}
        labelToCodeMap={excelLabelToCodeMap}
        onUpload={handleExcelUpload}
        customValidator={(data) => {
          // 사용설비 컬럼 검증: 쉼표 구분 각 이름이 equipmentMaster에 등록된 설비명인지
          const errors: any[] = [];
          const validNames = new Set(equipmentMaster.map((e) => e.equipment_name));
          for (const sheet of data) {
            sheet.rows.forEach((row, idx) => {
              const raw = String(row.equipment_list || "").trim();
              if (!raw) return;
              const names = raw.split(",").map((s) => s.trim()).filter(Boolean);
              const invalid = names.filter((n) => !validNames.has(n));
              if (invalid.length > 0) {
                errors.push({
                  sheet: sheet.sheetName,
                  row: idx + 2,
                  column: "사용설비(쉼표구분)",
                  message: `등록되지 않은 설비: ${invalid.join(", ")}`,
                });
              }
            });
          }
          return errors;
        }}
      />
    </div>
  );
}
