"use client";

/**
 * 설비정보 — 하드코딩 페이지
 *
 * 좌측: 설비 목록 (equipment_mng)
 * 우측: 탭 (기본정보 / 점검항목 / 소모품)
 * 점검항목 복사 기능 포함
 */

import React, { useState, useEffect, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import {
  Plus, Trash2, Save, Loader2, FileSpreadsheet, Download, Pencil,
  Wrench, ClipboardCheck, Package, Copy, Info, Settings2,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";
import { useAuth } from "@/hooks/useAuth";
import { toast } from "sonner";
import { DynamicSearchFilter, FilterValue } from "@/components/common/DynamicSearchFilter";
import { TableSettingsModal, TableSettings, loadTableSettings } from "@/components/common/TableSettingsModal";
import { DataGrid, DataGridColumn } from "@/components/common/DataGrid";
import { useConfirmDialog } from "@/components/common/ConfirmDialog";
import { FullscreenDialog } from "@/components/common/FullscreenDialog";
import { ExcelUploadModal } from "@/components/common/ExcelUploadModal";
import { exportToExcel } from "@/lib/utils/excelExport";
import { FormDatePicker } from "@/components/screen/filters/FormDatePicker";
import { autoDetectMultiTableConfig, TableChainConfig } from "@/lib/api/multiTableExcel";
import { MultiTableExcelUploadModal } from "@/components/common/MultiTableExcelUploadModal";
import { ImageUpload } from "@/components/common/ImageUpload";

const EQUIP_TABLE = "equipment_mng";
const INSPECTION_TABLE = "equipment_inspection_item";
const CONSUMABLE_TABLE = "equipment_consumable";

const LEFT_COLUMNS: DataGridColumn[] = [
  { key: "equipment_code", label: "설비코드", width: "w-[110px]" },
  { key: "equipment_name", label: "설비명", minWidth: "min-w-[130px]" },
  { key: "equipment_type", label: "설비유형", width: "w-[90px]" },
  { key: "manufacturer", label: "제조사", width: "w-[100px]" },
  { key: "installation_location", label: "설치장소", width: "w-[100px]" },
  { key: "operation_status", label: "가동상태", width: "w-[80px]" },
];

const INSPECTION_COLUMNS: DataGridColumn[] = [
  { key: "inspection_item", label: "점검항목", minWidth: "min-w-[120px]", editable: true },
  { key: "inspection_cycle", label: "점검주기", width: "w-[80px]" },
  { key: "inspection_method", label: "점검방법", width: "w-[80px]" },
  { key: "lower_limit", label: "하한치", width: "w-[70px]", editable: true },
  { key: "upper_limit", label: "상한치", width: "w-[70px]", editable: true },
  { key: "unit", label: "단위", width: "w-[60px]", editable: true },
  { key: "inspection_content", label: "점검내용", minWidth: "min-w-[150px]", editable: true },
];

const CONSUMABLE_COLUMNS: DataGridColumn[] = [
  { key: "image_path", label: "이미지", width: "w-[50px]", renderType: "image", sortable: false, filterable: false },
  { key: "consumable_name", label: "소모품명", minWidth: "min-w-[120px]", editable: true },
  { key: "replacement_cycle", label: "교체주기", width: "w-[90px]", editable: true },
  { key: "unit", label: "단위", width: "w-[60px]", editable: true },
  { key: "specification", label: "규격", width: "w-[100px]", editable: true },
  { key: "manufacturer", label: "제조사", width: "w-[100px]", editable: true },
];

export default function EquipmentInfoPage() {
  const { user } = useAuth();
  const { confirm, ConfirmDialogComponent } = useConfirmDialog();

  // 좌측
  const [equipments, setEquipments] = useState<any[]>([]);
  const [equipLoading, setEquipLoading] = useState(false);
  const [equipCount, setEquipCount] = useState(0);
  const [searchFilters, setSearchFilters] = useState<FilterValue[]>([]);
  const [tableSettingsOpen, setTableSettingsOpen] = useState(false);
  const [filterConfig, setFilterConfig] = useState<TableSettings["filters"] | undefined>();
  const [selectedEquipId, setSelectedEquipId] = useState<string | null>(null);

  // 우측 탭
  const [rightTab, setRightTab] = useState<"info" | "inspection" | "consumable">("info");
  const [inspections, setInspections] = useState<any[]>([]);
  const [inspectionLoading, setInspectionLoading] = useState(false);
  const [consumables, setConsumables] = useState<any[]>([]);
  const [consumableLoading, setConsumableLoading] = useState(false);

  // 카테고리
  const [catOptions, setCatOptions] = useState<Record<string, { code: string; label: string }[]>>({});

  // 모달
  const [equipModalOpen, setEquipModalOpen] = useState(false);
  const [equipEditMode, setEquipEditMode] = useState(false);
  const [equipForm, setEquipForm] = useState<Record<string, any>>({});
  const [saving, setSaving] = useState(false);

  // 기본정보 탭 편집 폼
  const [infoForm, setInfoForm] = useState<Record<string, any>>({});
  const [infoSaving, setInfoSaving] = useState(false);

  const [inspectionModalOpen, setInspectionModalOpen] = useState(false);
  const [inspectionForm, setInspectionForm] = useState<Record<string, any>>({});
  const [inspectionContinuous, setInspectionContinuous] = useState(false);

  const [consumableModalOpen, setConsumableModalOpen] = useState(false);
  const [consumableForm, setConsumableForm] = useState<Record<string, any>>({});
  const [consumableContinuous, setConsumableContinuous] = useState(false);
  const [consumableItemOptions, setConsumableItemOptions] = useState<any[]>([]);

  // 점검항목 복사
  const [copyModalOpen, setCopyModalOpen] = useState(false);
  const [copySourceEquip, setCopySourceEquip] = useState("");
  const [copyItems, setCopyItems] = useState<any[]>([]);
  const [copyChecked, setCopyChecked] = useState<Set<string>>(new Set());
  const [copyLoading, setCopyLoading] = useState(false);

  // 엑셀
  const [excelUploadOpen, setExcelUploadOpen] = useState(false);
  const [excelChainConfig, setExcelChainConfig] = useState<TableChainConfig | null>(null);
  const [excelDetecting, setExcelDetecting] = useState(false);

  const applyTableSettings = useCallback((settings: TableSettings) => {
    setFilterConfig(settings.filters);
  }, []);

  useEffect(() => {
    const saved = loadTableSettings("equipment-info");
    if (saved) applyTableSettings(saved);
  }, []);

  // 카테고리 로드
  useEffect(() => {
    const load = async () => {
      const optMap: Record<string, { code: string; label: string }[]> = {};
      const flatten = (vals: any[]): { code: string; label: string }[] => {
        const result: { code: string; label: string }[] = [];
        for (const v of vals) {
          result.push({ code: v.valueCode, label: v.valueLabel });
          if (v.children?.length) result.push(...flatten(v.children));
        }
        return result;
      };
      // equipment_mng 카테고리
      for (const col of ["equipment_type", "operation_status"]) {
        try {
          const res = await apiClient.get(`/table-categories/${EQUIP_TABLE}/${col}/values`);
          if (res.data?.success) optMap[col] = flatten(res.data.data || []);
        } catch { /* skip */ }
      }
      // inspection 카테고리
      for (const col of ["inspection_cycle", "inspection_method"]) {
        try {
          const res = await apiClient.get(`/table-categories/${INSPECTION_TABLE}/${col}/values`);
          if (res.data?.success) optMap[col] = flatten(res.data.data || []);
        } catch { /* skip */ }
      }
      setCatOptions(optMap);
    };
    load();
  }, []);

  const resolve = (col: string, code: string) => {
    if (!code) return "";
    return catOptions[col]?.find((o) => o.code === code)?.label || code;
  };

  // 설비 조회
  const fetchEquipments = useCallback(async () => {
    setEquipLoading(true);
    try {
      const filters = searchFilters.map((f) => ({ columnName: f.columnName, operator: f.operator, value: f.value }));
      const res = await apiClient.post(`/table-management/tables/${EQUIP_TABLE}/data`, {
        page: 1, size: 500,
        dataFilter: filters.length > 0 ? { enabled: true, filters } : undefined,
        autoFilter: true,
      });
      const raw = res.data?.data?.data || res.data?.data?.rows || [];
      setEquipments(raw.map((r: any) => ({
        ...r,
        equipment_type: resolve("equipment_type", r.equipment_type),
        operation_status: resolve("operation_status", r.operation_status),
      })));
      setEquipCount(res.data?.data?.total || raw.length);
    } catch { toast.error("설비 목록 조회 실패"); } finally { setEquipLoading(false); }
  }, [searchFilters, catOptions]);

  useEffect(() => { fetchEquipments(); }, [fetchEquipments]);

  const selectedEquip = equipments.find((e) => e.id === selectedEquipId);

  // 기본정보 탭 폼 초기화 (설비 선택 변경 시)
  useEffect(() => {
    if (selectedEquip) setInfoForm({ ...selectedEquip });
    else setInfoForm({});
  }, [selectedEquipId]); // eslint-disable-line react-hooks/exhaustive-deps

  // 기본정보 저장
  const handleInfoSave = async () => {
    if (!infoForm.id) return;
    setInfoSaving(true);
    try {
      const { id, created_date, updated_date, writer, company_code, ...fields } = infoForm;
      await apiClient.put(`/table-management/tables/${EQUIP_TABLE}/edit`, { originalData: { id }, updatedData: fields });
      toast.success("저장되었습니다.");
      fetchEquipments();
    } catch (err: any) { toast.error(err.response?.data?.message || "저장 실패"); }
    finally { setInfoSaving(false); }
  };

  // 우측: 점검항목 조회
  useEffect(() => {
    if (!selectedEquip?.equipment_code) { setInspections([]); return; }
    const fetch = async () => {
      setInspectionLoading(true);
      try {
        const res = await apiClient.post(`/table-management/tables/${INSPECTION_TABLE}/data`, {
          page: 1, size: 500,
          dataFilter: { enabled: true, filters: [{ columnName: "equipment_code", operator: "equals", value: selectedEquip.equipment_code }] },
          autoFilter: true,
        });
        const raw = res.data?.data?.data || res.data?.data?.rows || [];
        setInspections(raw.map((r: any) => ({
          ...r,
          inspection_cycle: resolve("inspection_cycle", r.inspection_cycle),
          inspection_method: resolve("inspection_method", r.inspection_method),
        })));
      } catch { setInspections([]); } finally { setInspectionLoading(false); }
    };
    fetch();
  }, [selectedEquip?.equipment_code, catOptions]);

  // 우측: 소모품 조회
  useEffect(() => {
    if (!selectedEquip?.equipment_code) { setConsumables([]); return; }
    const fetch = async () => {
      setConsumableLoading(true);
      try {
        const res = await apiClient.post(`/table-management/tables/${CONSUMABLE_TABLE}/data`, {
          page: 1, size: 500,
          dataFilter: { enabled: true, filters: [{ columnName: "equipment_code", operator: "equals", value: selectedEquip.equipment_code }] },
          autoFilter: true,
        });
        setConsumables(res.data?.data?.data || res.data?.data?.rows || []);
      } catch { setConsumables([]); } finally { setConsumableLoading(false); }
    };
    fetch();
  }, [selectedEquip?.equipment_code]);

  // 새로고침 헬퍼
  const refreshRight = () => {
    const eid = selectedEquipId;
    setSelectedEquipId(null);
    setTimeout(() => setSelectedEquipId(eid), 50);
  };

  // 설비 등록/수정
  const openEquipRegister = () => { setEquipForm({}); setEquipEditMode(false); setEquipModalOpen(true); };
  const openEquipEdit = () => { if (!selectedEquip) return; setEquipForm({ ...selectedEquip }); setEquipEditMode(true); setEquipModalOpen(true); };

  const handleEquipSave = async () => {
    if (!equipForm.equipment_name) { toast.error("설비명은 필수입니다."); return; }
    setSaving(true);
    try {
      const { id, created_date, updated_date, writer, company_code, ...fields } = equipForm;
      if (equipEditMode && id) {
        await apiClient.put(`/table-management/tables/${EQUIP_TABLE}/edit`, { originalData: { id }, updatedData: fields });
        toast.success("수정되었습니다.");
      } else {
        await apiClient.post(`/table-management/tables/${EQUIP_TABLE}/add`, fields);
        toast.success("등록되었습니다.");
      }
      setEquipModalOpen(false); fetchEquipments();
    } catch (err: any) { toast.error(err.response?.data?.message || "저장 실패"); } finally { setSaving(false); }
  };

  const handleEquipDelete = async () => {
    if (!selectedEquipId) return;
    const ok = await confirm("설비를 삭제하시겠습니까?", { description: "관련 점검항목, 소모품도 함께 삭제됩니다.", variant: "destructive", confirmText: "삭제" });
    if (!ok) return;
    try {
      await apiClient.delete(`/table-management/tables/${EQUIP_TABLE}/delete`, { data: [{ id: selectedEquipId }] });
      toast.success("삭제되었습니다."); setSelectedEquipId(null); fetchEquipments();
    } catch { toast.error("삭제 실패"); }
  };

  // 점검항목 추가
  const handleInspectionSave = async () => {
    if (!inspectionForm.inspection_item) { toast.error("점검항목명은 필수입니다."); return; }
    setSaving(true);
    try {
      await apiClient.post(`/table-management/tables/${INSPECTION_TABLE}/add`, {
        ...inspectionForm, equipment_code: selectedEquip?.equipment_code,
      });
      toast.success("추가되었습니다.");
      if (inspectionContinuous) {
        setInspectionForm({});
      } else {
        setInspectionModalOpen(false);
      }
      refreshRight();
    } catch (err: any) { toast.error(err.response?.data?.message || "저장 실패"); } finally { setSaving(false); }
  };

  // 소모품 추가
  // 소모품 품목 로드 (item_info에서 type 또는 division 라벨이 "소모품"인 것)
  const loadConsumableItems = async () => {
    try {
      const flatten = (vals: any[]): any[] => {
        const r: any[] = [];
        for (const v of vals) { r.push(v); if (v.children?.length) r.push(...flatten(v.children)); }
        return r;
      };

      // type과 division 카테고리 모두에서 "소모품" 코드 찾기
      const [typeRes, divRes] = await Promise.all([
        apiClient.get(`/table-categories/item_info/type/values`),
        apiClient.get(`/table-categories/item_info/division/values`),
      ]);
      const consumableType = flatten(typeRes.data?.data || []).find((t: any) => t.valueLabel === "소모품");
      const consumableDiv = flatten(divRes.data?.data || []).find((t: any) => t.valueLabel === "소모품");

      if (!consumableType && !consumableDiv) { setConsumableItemOptions([]); return; }

      // 두 필터 결과를 합산 (중복 제거)
      const filters: any[] = [];
      if (consumableType) filters.push({ columnName: "type", operator: "equals", value: consumableType.valueCode });
      if (consumableDiv) filters.push({ columnName: "division", operator: "equals", value: consumableDiv.valueCode });

      const results = await Promise.all(filters.map((f) =>
        apiClient.post(`/table-management/tables/item_info/data`, {
          page: 1, size: 500,
          dataFilter: { enabled: true, filters: [f] },
          autoFilter: true,
        })
      ));

      const allItems = new Map<string, any>();
      for (const res of results) {
        const rows = res.data?.data?.data || res.data?.data?.rows || [];
        for (const row of rows) allItems.set(row.id, row);
      }
      setConsumableItemOptions(Array.from(allItems.values()));
    } catch { setConsumableItemOptions([]); }
  };

  const handleConsumableSave = async () => {
    if (!consumableForm.consumable_name) { toast.error("소모품명은 필수입니다."); return; }
    setSaving(true);
    try {
      await apiClient.post(`/table-management/tables/${CONSUMABLE_TABLE}/add`, {
        ...consumableForm, equipment_code: selectedEquip?.equipment_code,
      });
      toast.success("추가되었습니다.");
      if (consumableContinuous) {
        setConsumableForm({});
      } else {
        setConsumableModalOpen(false);
      }
      refreshRight();
    } catch (err: any) { toast.error(err.response?.data?.message || "저장 실패"); } finally { setSaving(false); }
  };

  // 점검항목 복사: 소스 설비 선택 시 점검항목 로드
  const loadCopyItems = async (equipCode: string) => {
    setCopySourceEquip(equipCode);
    setCopyChecked(new Set());
    if (!equipCode) { setCopyItems([]); return; }
    setCopyLoading(true);
    try {
      const res = await apiClient.post(`/table-management/tables/${INSPECTION_TABLE}/data`, {
        page: 1, size: 500,
        dataFilter: { enabled: true, filters: [{ columnName: "equipment_code", operator: "equals", value: equipCode }] },
        autoFilter: true,
      });
      setCopyItems(res.data?.data?.data || res.data?.data?.rows || []);
    } catch { setCopyItems([]); } finally { setCopyLoading(false); }
  };

  const handleCopyApply = async () => {
    const selected = copyItems.filter((i) => copyChecked.has(i.id));
    if (selected.length === 0) { toast.error("복사할 항목을 선택해주세요."); return; }
    setSaving(true);
    try {
      for (const item of selected) {
        const { id, created_date, updated_date, writer, company_code, equipment_code, ...fields } = item;
        await apiClient.post(`/table-management/tables/${INSPECTION_TABLE}/add`, {
          ...fields, equipment_code: selectedEquip?.equipment_code,
        });
      }
      toast.success(`${selected.length}개 점검항목이 복사되었습니다.`);
      setCopyModalOpen(false); refreshRight();
    } catch { toast.error("복사 실패"); } finally { setSaving(false); }
  };

  // 엑셀
  const handleExcelDownload = async () => {
    if (equipments.length === 0) return;
    await exportToExcel(equipments.map((e) => ({
      설비코드: e.equipment_code, 설비명: e.equipment_name, 설비유형: e.equipment_type,
      제조사: e.manufacturer, 모델명: e.model_name, 설치장소: e.installation_location,
      도입일자: e.introduction_date, 가동상태: e.operation_status,
    })), "설비정보.xlsx", "설비");
    toast.success("다운로드 완료");
  };

  // 셀렉트 렌더링 헬퍼
  const catSelect = (key: string, value: string, onChange: (v: string) => void, placeholder: string) => (
    <Select value={value || ""} onValueChange={onChange}>
      <SelectTrigger className="h-9"><SelectValue placeholder={placeholder} /></SelectTrigger>
      <SelectContent>
        {(catOptions[key] || []).map((o) => <SelectItem key={o.code} value={o.code}>{o.label}</SelectItem>)}
      </SelectContent>
    </Select>
  );

  return (
    <div className="flex h-full flex-col gap-3 p-3">
      <DynamicSearchFilter tableName={EQUIP_TABLE} filterId="equipment-info" onFilterChange={setSearchFilters} dataCount={equipCount}
        externalFilterConfig={filterConfig}
        extraActions={
          <div className="flex gap-1.5">
            <Button variant="outline" size="sm" className="h-9" onClick={() => setTableSettingsOpen(true)}>
              <Settings2 className="w-4 h-4 mr-1.5" /> 테이블 설정
            </Button>
            <Button variant="outline" size="sm" className="h-9" disabled={excelDetecting}
              onClick={async () => {
                setExcelDetecting(true);
                try {
                  const r = await autoDetectMultiTableConfig(EQUIP_TABLE);
                  if (r.success && r.data) { setExcelChainConfig(r.data); setExcelUploadOpen(true); }
                  else toast.error("테이블 구조 분석 실패");
                } catch { toast.error("오류"); } finally { setExcelDetecting(false); }
              }}>
              {excelDetecting ? <Loader2 className="w-3.5 h-3.5 mr-1 animate-spin" /> : <FileSpreadsheet className="w-3.5 h-3.5 mr-1" />} 엑셀 업로드
            </Button>
            <Button variant="outline" size="sm" className="h-9" onClick={handleExcelDownload}>
              <Download className="w-3.5 h-3.5 mr-1" /> 엑셀 다운로드
            </Button>
          </div>
        }
      />

      <div className="flex-1 overflow-hidden border rounded-lg bg-background shadow-sm">
        <ResizablePanelGroup direction="horizontal">
          {/* 좌측: 설비 목록 */}
          <ResizablePanel defaultSize={40} minSize={25}>
            <div className="flex flex-col h-full">
              <div className="flex items-center justify-between p-3 border-b bg-muted/10 shrink-0">
                <div className="font-semibold flex items-center gap-2 text-sm">
                  <Wrench className="w-4 h-4" /> 설비 목록 <Badge variant="secondary" className="font-normal">{equipCount}건</Badge>
                </div>
                <div className="flex gap-1.5">
                  <Button size="sm" onClick={openEquipRegister}><Plus className="w-3.5 h-3.5 mr-1" /> 등록</Button>
                  <Button variant="outline" size="sm" disabled={!selectedEquipId} onClick={openEquipEdit}><Pencil className="w-3.5 h-3.5 mr-1" /> 수정</Button>
                  <Button variant="destructive" size="sm" disabled={!selectedEquipId} onClick={handleEquipDelete}><Trash2 className="w-3.5 h-3.5 mr-1" /> 삭제</Button>
                </div>
              </div>
              <DataGrid gridId="equip-left" columns={LEFT_COLUMNS} data={equipments} loading={equipLoading}
                selectedId={selectedEquipId} onSelect={setSelectedEquipId} onRowDoubleClick={() => openEquipEdit()}
                emptyMessage="등록된 설비가 없습니다" />
            </div>
          </ResizablePanel>

          <ResizableHandle withHandle />

          {/* 우측: 탭 */}
          <ResizablePanel defaultSize={60} minSize={30}>
            <div className="flex flex-col h-full">
              <div className="flex items-center justify-between p-2 border-b bg-muted/10 shrink-0">
                <div className="flex items-center gap-1">
                  {([["info", "기본정보", Info], ["inspection", "점검항목", ClipboardCheck], ["consumable", "소모품", Package]] as const).map(([tab, label, Icon]) => (
                    <button key={tab} onClick={() => setRightTab(tab)}
                      className={cn("px-3 py-1.5 text-sm rounded-md transition-colors flex items-center gap-1",
                        rightTab === tab ? "bg-primary text-primary-foreground font-medium" : "hover:bg-muted text-muted-foreground")}>
                      <Icon className="w-3.5 h-3.5" />{label}
                      {tab === "inspection" && inspections.length > 0 && <Badge variant="secondary" className="ml-1 text-[10px] px-1">{inspections.length}</Badge>}
                      {tab === "consumable" && consumables.length > 0 && <Badge variant="secondary" className="ml-1 text-[10px] px-1">{consumables.length}</Badge>}
                    </button>
                  ))}
                  {selectedEquip && <Badge variant="outline" className="font-normal ml-2 text-xs">{selectedEquip.equipment_name}</Badge>}
                </div>
                <div className="flex gap-1.5">
                  {rightTab === "inspection" && (
                    <>
                      <Button variant="outline" size="sm" disabled={!selectedEquipId} onClick={() => { setInspectionForm({}); setInspectionModalOpen(true); }}>
                        <Plus className="w-3.5 h-3.5 mr-1" /> 추가
                      </Button>
                      <Button variant="outline" size="sm" disabled={!selectedEquipId} onClick={() => { setCopySourceEquip(""); setCopyItems([]); setCopyChecked(new Set()); setCopyModalOpen(true); }}>
                        <Copy className="w-3.5 h-3.5 mr-1" /> 복사
                      </Button>
                    </>
                  )}
                  {rightTab === "consumable" && (
                    <Button variant="outline" size="sm" disabled={!selectedEquipId} onClick={() => { setConsumableForm({}); loadConsumableItems(); setConsumableModalOpen(true); }}>
                      <Plus className="w-3.5 h-3.5 mr-1" /> 추가
                    </Button>
                  )}
                </div>
              </div>

              {!selectedEquipId ? (
                <div className="flex-1 flex items-center justify-center text-muted-foreground text-sm">좌측에서 설비를 선택하세요</div>
              ) : rightTab === "info" ? (
                <div className="p-4 overflow-auto">
                  <div className="flex justify-end mb-3">
                    <Button size="sm" onClick={handleInfoSave} disabled={infoSaving}>
                      {infoSaving ? <Loader2 className="w-4 h-4 mr-1.5 animate-spin" /> : <Save className="w-4 h-4 mr-1.5" />} 저장
                    </Button>
                  </div>
                  <div className="grid grid-cols-2 gap-4">
                    <div className="space-y-1.5">
                      <Label className="text-sm text-muted-foreground">설비코드</Label>
                      <Input value={infoForm.equipment_code || ""} className="h-9 bg-muted/50" disabled />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">설비명</Label>
                      <Input value={infoForm.equipment_name || ""} onChange={(e) => setInfoForm((p) => ({ ...p, equipment_name: e.target.value }))} className="h-9" />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">설비유형</Label>
                      {catSelect("equipment_type", infoForm.equipment_type, (v) => setInfoForm((p) => ({ ...p, equipment_type: v })), "설비유형")}
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">설치장소</Label>
                      <Input value={infoForm.installation_location || ""} onChange={(e) => setInfoForm((p) => ({ ...p, installation_location: e.target.value }))} className="h-9" />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">제조사</Label>
                      <Input value={infoForm.manufacturer || ""} onChange={(e) => setInfoForm((p) => ({ ...p, manufacturer: e.target.value }))} className="h-9" />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">모델명</Label>
                      <Input value={infoForm.model_name || ""} onChange={(e) => setInfoForm((p) => ({ ...p, model_name: e.target.value }))} className="h-9" />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">도입일자</Label>
                      <FormDatePicker value={infoForm.introduction_date || ""} onChange={(v) => setInfoForm((p) => ({ ...p, introduction_date: v }))} placeholder="도입일자" />
                    </div>
                    <div className="space-y-1.5">
                      <Label className="text-sm">가동상태</Label>
                      {catSelect("operation_status", infoForm.operation_status, (v) => setInfoForm((p) => ({ ...p, operation_status: v })), "가동상태")}
                    </div>
                    <div className="space-y-1.5 col-span-2">
                      <Label className="text-sm">비고</Label>
                      <Input value={infoForm.remarks || ""} onChange={(e) => setInfoForm((p) => ({ ...p, remarks: e.target.value }))} className="h-9" />
                    </div>
                    <div className="space-y-1.5 col-span-2">
                      <Label className="text-sm">이미지</Label>
                      <ImageUpload value={infoForm.image_path} onChange={(v) => setInfoForm((p) => ({ ...p, image_path: v }))}
                        tableName={EQUIP_TABLE} recordId={infoForm.id} columnName="image_path" />
                    </div>
                  </div>
                </div>
              ) : rightTab === "inspection" ? (
                <DataGrid gridId="equip-inspection" columns={INSPECTION_COLUMNS} data={inspections} loading={inspectionLoading}
                  showRowNumber={false} tableName={INSPECTION_TABLE} emptyMessage="점검항목이 없습니다"
                  onCellEdit={() => refreshRight()} />
              ) : (
                <DataGrid gridId="equip-consumable" columns={CONSUMABLE_COLUMNS} data={consumables} loading={consumableLoading}
                  showRowNumber={false} tableName={CONSUMABLE_TABLE} emptyMessage="소모품이 없습니다"
                  onCellEdit={() => refreshRight()} />
              )}
            </div>
          </ResizablePanel>
        </ResizablePanelGroup>
      </div>

      {/* 설비 등록/수정 모달 */}
      <FullscreenDialog open={equipModalOpen} onOpenChange={setEquipModalOpen}
        title={equipEditMode ? "설비 수정" : "설비 등록"} description={equipEditMode ? "설비 정보를 수정합니다." : "새로운 설비를 등록합니다."}
        defaultMaxWidth="max-w-2xl"
        footer={<><Button variant="outline" onClick={() => setEquipModalOpen(false)}>취소</Button>
          <Button onClick={handleEquipSave} disabled={saving}>{saving ? <Loader2 className="w-4 h-4 mr-1.5 animate-spin" /> : <Save className="w-4 h-4 mr-1.5" />} 저장</Button></>}>
        <div className="grid grid-cols-2 gap-4 py-4">
          <div className="space-y-1.5"><Label className="text-sm">설비코드</Label>
            <Input value={equipForm.equipment_code || ""} onChange={(e) => setEquipForm((p) => ({ ...p, equipment_code: e.target.value }))} placeholder="설비코드" className="h-9" disabled={equipEditMode} /></div>
          <div className="space-y-1.5"><Label className="text-sm">설비명 <span className="text-destructive">*</span></Label>
            <Input value={equipForm.equipment_name || ""} onChange={(e) => setEquipForm((p) => ({ ...p, equipment_name: e.target.value }))} placeholder="설비명" className="h-9" /></div>
          <div className="space-y-1.5"><Label className="text-sm">설비유형</Label>
            {catSelect("equipment_type", equipForm.equipment_type, (v) => setEquipForm((p) => ({ ...p, equipment_type: v })), "설비유형")}</div>
          <div className="space-y-1.5"><Label className="text-sm">가동상태</Label>
            {catSelect("operation_status", equipForm.operation_status, (v) => setEquipForm((p) => ({ ...p, operation_status: v })), "가동상태")}</div>
          <div className="space-y-1.5"><Label className="text-sm">설치장소</Label>
            <Input value={equipForm.installation_location || ""} onChange={(e) => setEquipForm((p) => ({ ...p, installation_location: e.target.value }))} placeholder="설치장소" className="h-9" /></div>
          <div className="space-y-1.5"><Label className="text-sm">제조사</Label>
            <Input value={equipForm.manufacturer || ""} onChange={(e) => setEquipForm((p) => ({ ...p, manufacturer: e.target.value }))} placeholder="제조사" className="h-9" /></div>
          <div className="space-y-1.5"><Label className="text-sm">모델명</Label>
            <Input value={equipForm.model_name || ""} onChange={(e) => setEquipForm((p) => ({ ...p, model_name: e.target.value }))} placeholder="모델명" className="h-9" /></div>
          <div className="space-y-1.5"><Label className="text-sm">도입일자</Label>
            <FormDatePicker value={equipForm.introduction_date || ""} onChange={(v) => setEquipForm((p) => ({ ...p, introduction_date: v }))} placeholder="도입일자" /></div>
          <div className="space-y-1.5 col-span-2"><Label className="text-sm">비고</Label>
            <Input value={equipForm.remarks || ""} onChange={(e) => setEquipForm((p) => ({ ...p, remarks: e.target.value }))} placeholder="비고" className="h-9" /></div>
          <div className="space-y-1.5 col-span-2"><Label className="text-sm">이미지</Label>
            <ImageUpload value={equipForm.image_path} onChange={(v) => setEquipForm((p) => ({ ...p, image_path: v }))}
              tableName={EQUIP_TABLE} recordId={equipForm.id} columnName="image_path" /></div>
        </div>
      </FullscreenDialog>

      {/* 점검항목 추가 모달 */}
      <Dialog open={inspectionModalOpen} onOpenChange={setInspectionModalOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader><DialogTitle>점검항목 추가</DialogTitle><DialogDescription>{selectedEquip?.equipment_name}에 점검항목을 추가합니다.</DialogDescription></DialogHeader>
          <div className="space-y-4 py-4">
            <div className="space-y-1.5"><Label className="text-sm">점검항목 <span className="text-destructive">*</span></Label>
              <Input value={inspectionForm.inspection_item || ""} onChange={(e) => setInspectionForm((p) => ({ ...p, inspection_item: e.target.value }))} placeholder="점검항목" className="h-9" /></div>
            <div className="grid grid-cols-2 gap-4">
              <div className="space-y-1.5"><Label className="text-sm">점검주기</Label>
                {catSelect("inspection_cycle", inspectionForm.inspection_cycle, (v) => setInspectionForm((p) => ({ ...p, inspection_cycle: v })), "점검주기")}</div>
              <div className="space-y-1.5"><Label className="text-sm">점검방법</Label>
                {catSelect("inspection_method", inspectionForm.inspection_method, (v) => setInspectionForm((p) => ({ ...p, inspection_method: v })), "점검방법")}</div>
              <div className="space-y-1.5"><Label className="text-sm">하한치</Label>
                <Input value={inspectionForm.lower_limit || ""} onChange={(e) => setInspectionForm((p) => ({ ...p, lower_limit: e.target.value }))} placeholder="하한치" className="h-9" /></div>
              <div className="space-y-1.5"><Label className="text-sm">상한치</Label>
                <Input value={inspectionForm.upper_limit || ""} onChange={(e) => setInspectionForm((p) => ({ ...p, upper_limit: e.target.value }))} placeholder="상한치" className="h-9" /></div>
              <div className="space-y-1.5"><Label className="text-sm">단위</Label>
                <Input value={inspectionForm.unit || ""} onChange={(e) => setInspectionForm((p) => ({ ...p, unit: e.target.value }))} placeholder="단위" className="h-9" /></div>
            </div>
            <div className="space-y-1.5"><Label className="text-sm">점검내용</Label>
              <Input value={inspectionForm.inspection_content || ""} onChange={(e) => setInspectionForm((p) => ({ ...p, inspection_content: e.target.value }))} placeholder="점검내용" className="h-9" /></div>
          </div>
          <DialogFooter className="flex items-center justify-between sm:justify-between">
            <label className="flex items-center gap-2 text-sm cursor-pointer">
              <Checkbox checked={inspectionContinuous} onCheckedChange={(c) => setInspectionContinuous(!!c)} />
              저장 후 계속 입력
            </label>
            <div className="flex gap-2">
              <Button variant="outline" onClick={() => setInspectionModalOpen(false)}>취소</Button>
              <Button onClick={handleInspectionSave} disabled={saving}><Save className="w-4 h-4 mr-1.5" /> 저장</Button>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 소모품 추가 모달 */}
      <Dialog open={consumableModalOpen} onOpenChange={setConsumableModalOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader><DialogTitle>소모품 추가</DialogTitle><DialogDescription>{selectedEquip?.equipment_name}에 소모품을 추가합니다.</DialogDescription></DialogHeader>
          <div className="grid grid-cols-2 gap-4 py-4">
            <div className="space-y-1.5 col-span-2"><Label className="text-sm">소모품명 <span className="text-destructive">*</span></Label>
              {consumableItemOptions.length > 0 ? (
                <Select value={consumableForm.consumable_name || ""} onValueChange={(v) => {
                  const item = consumableItemOptions.find((i) => (i.item_name || i.item_number) === v);
                  setConsumableForm((p) => ({
                    ...p,
                    consumable_name: v,
                    specification: item?.size || p.specification || "",
                    unit: item?.unit || p.unit || "",
                    manufacturer: item?.manufacturer || p.manufacturer || "",
                  }));
                }}>
                  <SelectTrigger className="h-9"><SelectValue placeholder="소모품 선택" /></SelectTrigger>
                  <SelectContent>
                    {consumableItemOptions.map((item) => (
                      <SelectItem key={item.id} value={item.item_name || item.item_number}>
                        {item.item_name}{item.size ? ` (${item.size})` : ""}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              ) : (
                <div>
                  <Input value={consumableForm.consumable_name || ""} onChange={(e) => setConsumableForm((p) => ({ ...p, consumable_name: e.target.value }))}
                    placeholder="소모품명 직접 입력" className="h-9" />
                  <p className="text-xs text-muted-foreground mt-1">품목정보에 소모품 타입 품목을 등록하면 선택 가능합니다</p>
                </div>
              )}</div>
            <div className="space-y-1.5"><Label className="text-sm">교체주기</Label>
              <Input value={consumableForm.replacement_cycle || ""} onChange={(e) => setConsumableForm((p) => ({ ...p, replacement_cycle: e.target.value }))} placeholder="교체주기" className="h-9" /></div>
            <div className="space-y-1.5"><Label className="text-sm">단위</Label>
              <Input value={consumableForm.unit || ""} onChange={(e) => setConsumableForm((p) => ({ ...p, unit: e.target.value }))} placeholder="단위" className="h-9" /></div>
            <div className="space-y-1.5"><Label className="text-sm">규격</Label>
              <Input value={consumableForm.specification || ""} onChange={(e) => setConsumableForm((p) => ({ ...p, specification: e.target.value }))} placeholder="규격" className="h-9" /></div>
            <div className="space-y-1.5"><Label className="text-sm">제조사</Label>
              <Input value={consumableForm.manufacturer || ""} onChange={(e) => setConsumableForm((p) => ({ ...p, manufacturer: e.target.value }))} placeholder="제조사" className="h-9" /></div>
            <div className="space-y-1.5 col-span-2"><Label className="text-sm">이미지</Label>
              <ImageUpload value={consumableForm.image_path} onChange={(v) => setConsumableForm((p) => ({ ...p, image_path: v }))}
                tableName={CONSUMABLE_TABLE} columnName="image_path" /></div>
          </div>
          <DialogFooter className="flex items-center justify-between sm:justify-between">
            <label className="flex items-center gap-2 text-sm cursor-pointer">
              <Checkbox checked={consumableContinuous} onCheckedChange={(c) => setConsumableContinuous(!!c)} />
              저장 후 계속 입력
            </label>
            <div className="flex gap-2">
              <Button variant="outline" onClick={() => setConsumableModalOpen(false)}>취소</Button>
              <Button onClick={handleConsumableSave} disabled={saving}><Save className="w-4 h-4 mr-1.5" /> 저장</Button>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 점검항목 복사 모달 */}
      <Dialog open={copyModalOpen} onOpenChange={setCopyModalOpen}>
        <DialogContent className="max-w-2xl max-h-[70vh]">
          <DialogHeader><DialogTitle>점검항목 복사</DialogTitle>
            <DialogDescription>다른 설비의 점검항목을 선택하여 {selectedEquip?.equipment_name}에 복사합니다.</DialogDescription></DialogHeader>
          <div className="space-y-3">
            <div className="space-y-1.5">
              <Label className="text-sm">소스 설비 선택</Label>
              <Select value={copySourceEquip} onValueChange={(v) => loadCopyItems(v)}>
                <SelectTrigger className="h-9"><SelectValue placeholder="복사할 설비 선택" /></SelectTrigger>
                <SelectContent>
                  {equipments.filter((e) => e.equipment_code !== selectedEquip?.equipment_code).map((e) => (
                    <SelectItem key={e.equipment_code} value={e.equipment_code}>{e.equipment_name} ({e.equipment_code})</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="border rounded-lg overflow-auto max-h-[300px]">
              {copyLoading ? (
                <div className="flex items-center justify-center py-8"><Loader2 className="w-6 h-6 animate-spin text-muted-foreground" /></div>
              ) : copyItems.length === 0 ? (
                <div className="text-center text-muted-foreground py-8 text-sm">{copySourceEquip ? "점검항목이 없습니다" : "설비를 선택하세요"}</div>
              ) : (
                <Table>
                  <TableHeader className="sticky top-0 bg-background z-10">
                    <TableRow>
                      <TableHead className="w-[40px] text-center">
                        <input type="checkbox" checked={copyItems.length > 0 && copyChecked.size === copyItems.length}
                          onChange={(e) => { if (e.target.checked) setCopyChecked(new Set(copyItems.map((i) => i.id))); else setCopyChecked(new Set()); }} />
                      </TableHead>
                      <TableHead>점검항목</TableHead><TableHead className="w-[80px]">점검주기</TableHead>
                      <TableHead className="w-[80px]">점검방법</TableHead><TableHead className="w-[70px]">하한</TableHead>
                      <TableHead className="w-[70px]">상한</TableHead><TableHead className="w-[60px]">단위</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {copyItems.map((item) => (
                      <TableRow key={item.id} className={cn("cursor-pointer", copyChecked.has(item.id) && "bg-primary/5")}
                        onClick={() => setCopyChecked((prev) => { const n = new Set(prev); if (n.has(item.id)) n.delete(item.id); else n.add(item.id); return n; })}>
                        <TableCell className="text-center"><input type="checkbox" checked={copyChecked.has(item.id)} readOnly /></TableCell>
                        <TableCell className="text-sm">{item.inspection_item}</TableCell>
                        <TableCell className="text-xs">{resolve("inspection_cycle", item.inspection_cycle)}</TableCell>
                        <TableCell className="text-xs">{resolve("inspection_method", item.inspection_method)}</TableCell>
                        <TableCell className="text-xs">{item.lower_limit || "-"}</TableCell>
                        <TableCell className="text-xs">{item.upper_limit || "-"}</TableCell>
                        <TableCell className="text-xs">{item.unit || "-"}</TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              )}
            </div>
          </div>
          <DialogFooter>
            <div className="flex items-center gap-2 w-full justify-between">
              <span className="text-sm text-muted-foreground">{copyChecked.size}개 선택됨</span>
              <div className="flex gap-2">
                <Button variant="outline" onClick={() => setCopyModalOpen(false)}>취소</Button>
                <Button onClick={handleCopyApply} disabled={saving || copyChecked.size === 0}>
                  {saving ? <Loader2 className="w-4 h-4 mr-1.5 animate-spin" /> : <Copy className="w-4 h-4 mr-1.5" />} 복사 적용
                </Button>
              </div>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 엑셀 업로드 (멀티테이블) */}
      {excelChainConfig && (
        <MultiTableExcelUploadModal open={excelUploadOpen}
          onOpenChange={(open) => { setExcelUploadOpen(open); if (!open) setExcelChainConfig(null); }}
          config={excelChainConfig} onSuccess={() => { fetchEquipments(); refreshRight(); }} />
      )}

      <TableSettingsModal
        open={tableSettingsOpen}
        onOpenChange={setTableSettingsOpen}
        tableName={EQUIP_TABLE}
        settingsId="equipment-info"
        onSave={applyTableSettings}
      />

      {ConfirmDialogComponent}
    </div>
  );
}
