"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
} from "@/components/ui/select";
import {
  Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,
} from "@/components/ui/dialog";
import { Plus, Save, Trash2, Loader2, Search, Pencil, CheckCircle2, XCircle, Copy, Send } from "lucide-react";
import { toast } from "sonner";
import { useAuth } from "@/hooks/useAuth";
import { useConfirmDialog } from "@/components/common/ConfirmDialog";
import { DataGrid, DataGridColumn } from "@/components/common/DataGrid";
import { CustomerSelect } from "@/components/common/CustomerSelect";
import { PartSelect } from "@/components/common/PartSelect";
import { CommCodeSelect } from "@/components/common/CommCodeSelect";
import { PageHeader } from "@/components/common/PageHeader";
import { CompactFilterBar, CompactFilterField, CompactDateRange } from "@/components/common/CompactFilterBar";
import { ItemSearchDialog, ItemRow } from "@/components/common/ItemSearchDialog";
import { AttachmentDialog } from "@/components/common/AttachmentDialog";
import { OrderFormViewDialog } from "@/components/sales/OrderFormViewDialog";
import { OrderRegistDialog } from "@/components/sales/OrderRegistDialog";
import { salesOrderMgmtApi, OrderRow, OrderBody, OrderItem } from "@/lib/api/salesOrderMgmt";
import { exportToExcel } from "@/lib/utils/excelExport";

// wace_plm orderMgmtList.jsp 컬럼 순서/라벨에 맞춤
const GRID_COLUMNS: DataGridColumn[] = [
  { key: "contract_no", label: "영업번호", width: "w-[125px]", frozen: true },
  { key: "category_name", label: "주문유형", width: "w-[115px]", align: "center" },
  { key: "order_date", label: "발주일", width: "w-[115px]", align: "center" },
  { key: "po_no", label: "발주번호", width: "w-[140px]" },
  { key: "earliest_due_date_label", label: "요청납기", width: "w-[160px]", align: "center" },
  { key: "customer_name", label: "고객사", width: "w-[160px]" },
  { key: "item_summary", label: "품명", width: "w-[200px]" },
  { key: "order_quantity", label: "수주수량", width: "w-[115px]", align: "right", formatNumber: true },
  { key: "cancel_qty_sum", label: "수주취소", width: "w-[115px]", align: "right", formatNumber: true },
  { key: "paid_type_name", label: "유/무상", width: "w-[100px]", align: "center" },
  { key: "contract_result_name", label: "수주상태", width: "w-[115px]", align: "center" },
  { key: "order_supply_price_sum", label: "공급가액", width: "w-[130px]", formatMoney: true },
  { key: "order_vat_sum", label: "부가세", width: "w-[115px]", formatMoney: true },
  { key: "order_total_amount_sum", label: "총액", width: "w-[120px]", formatMoney: true },
  { key: "order_total_amount_krw", label: "원화총액", width: "w-[130px]", formatMoney: true },
  { key: "cu01_cnt", label: "주문서첨부", width: "w-[115px]", align: "center", renderType: "clip" },
  { key: "has_order_data", label: "주문서", width: "w-[100px]", align: "center", renderType: "folder" },
  { key: "customer_request", label: "고객사요청사항", width: "w-[180px]" },
  { key: "order_appr_status", label: "결재상태", width: "w-[115px]", align: "center" },
  { key: "contract_currency_name", label: "환종", width: "w-[95px]", align: "center" },
  { key: "exchange_rate", label: "환율", width: "w-[95px]", formatMoney: true },
  { key: "serial_no", label: "S/N", width: "w-[140px]" },
  { key: "part_no", label: "품번", width: "w-[120px]" },
  { key: "writer_name", label: "작성자", width: "w-[115px]" },
  /* wace orderMgmtList.jsp 429~434 — 비활성(주석) 컬럼. 활성화 시 아래 주석 해제.
  { key: "product_name", label: "제품구분", width: "w-[90px]", align: "center" },
  { key: "area_name", label: "국내/해외", width: "w-[90px]", align: "center" },
  { key: "receipt_date", label: "접수일", width: "w-[110px]", align: "center" },
  */
];

const PAID_TYPES: Record<string, string> = { paid: "유상", free: "무상" };
// wace 운영 contract_result 코드 (parent=0000963 영업구분)
//   0000964 수주 / 0000965 Cancel / 0000966 Hold / 0000968 수주(FCST)
//   대기는 NULL/빈값이 운영 패턴 (wace 신규 등록 시 NULL)
//   "수주확정" 버튼은 단일 코드로 직행하지 않고, 다이얼로그에서 사용자가 선택
const CONTRACT_RESULTS = [
  { value: "", label: "전체" },
  { value: "0000964", label: "수주" },
  { value: "0000968", label: "수주(FCST)" },
  { value: "0000966", label: "Hold" },
  { value: "0000965", label: "Cancel" },
];

// wace estimateAndOrderRegistFormPopup 라인 — 제품구분/S/N/요청납기/반납사유/고객요청사항 포함
const EMPTY_ITEM: OrderItem = {
  seq: 1,
  product: "", part_objid: "", part_no: "", part_name: "",
  serials: [],
  due_date: "", return_reason: "", customer_request: "",
  quantity: 1,
  order_quantity: "", order_unit_price: "0", order_supply_price: "0",
  order_vat: "0", order_total_amount: "0",
};

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

  const [rows, setRows] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [selected, setSelected] = useState<OrderRow | null>(null);
  // wace orderMgmtList.jsp 활성 9개 (1줄 7개 / 2줄 2개)
  const [searchForm, setSearchForm] = useState({
    category_cd: "", search_poNo: "", customer_objid: "",
    search_partObjId: "", search_partName: "", search_serialNo: "", contract_result: "",
    order_start_date: "", order_end_date: "",
    due_start_date: "", due_end_date: "",
  });
  const [dialogOpen, setDialogOpen] = useState(false);
  const [dialogMode, setDialogMode] = useState<"create" | "edit">("create");
  const [saving, setSaving] = useState(false);
  const [form, setForm] = useState<OrderBody>({
    contract_currency: "KRW", paid_type: "paid",
    items: [],
  });

  // 품목 검색 모달 (라인별 진입)
  const [itemDialogOpen, setItemDialogOpen] = useState(false);
  const [itemSearchTargetIdx, setItemSearchTargetIdx] = useState<number | null>(null);

  // S/N 관리 모달 + 연속번호 생성 (wace fn_openItemSnPopup / fn_openItemSequentialSnPopup)
  const [serialDialogOpen, setSerialDialogOpen] = useState(false);
  const [serialDialogIdx, setSerialDialogIdx] = useState<number | null>(null);
  const [serialDraft, setSerialDraft] = useState<string[]>([]);
  const [serialInput, setSerialInput] = useState("");
  const [seqDialogOpen, setSeqDialogOpen] = useState(false);
  const [seqStartNo, setSeqStartNo] = useState("");
  const [seqCount, setSeqCount] = useState("");

  // 첨부파일 다이얼로그 (주문서첨부 클립 컬럼 클릭 시)
  const [attachDialogOpen, setAttachDialogOpen] = useState(false);
  const [attachContext, setAttachContext] = useState<{
    targetObjid: string;
    docType: string | string[];
    uploadDocType: string;
    uploadDocTypeName?: string;
    title: string;
  } | null>(null);

  // 주문서 자동생성 뷰 다이얼로그 (has_order_data 폴더 컬럼 클릭)
  const [orderFormOpen, setOrderFormOpen] = useState(false);
  const [orderFormObjid, setOrderFormObjid] = useState<string | null>(null);

  // 견적요청에서 시작된 행의 수주등록 다이얼로그 (wace orderRegistFormPopup 1:1)
  //   - is_direct_order != 'Y' 행을 수정할 때 사용 (헤더 4개 + 라인 ORDER_*만 입력)
  //   - 직접등록 통합폼(estimateAndOrderRegistFormPopup)과 완전 분리
  const [orderRegistOpen, setOrderRegistOpen] = useState(false);
  const [orderRegistContract, setOrderRegistContract] = useState<{ objid: string; contractNo: string } | null>(null);

  // 수주확정 다이얼로그 (wace fn_openOrderConfirmPopup 이식 — 상태 select)
  const [confirmStatusOpen, setConfirmStatusOpen] = useState(false);
  const [confirmStatusValue, setConfirmStatusValue] = useState<string>("");

  // 수주취소 다이얼로그 (wace fn_openOrderCancelPopup 이식 — 라인별 cancel_qty)
  const [cancelDialogOpen, setCancelDialogOpen] = useState(false);
  const [cancelLines, setCancelLines] = useState<{
    objid: string; part_no: string; part_name: string; order_qty: number; cancel_qty: string;
  }[]>([]);
  const [cancelSaving, setCancelSaving] = useState(false);

  const gridColumns = useMemo<DataGridColumn[]>(
    () => GRID_COLUMNS.map((col) => {
      if (col.key === "cu01_cnt") {
        return {
          ...col,
          onClick: (row) => {
            setAttachContext({
              targetObjid: String(row.objid),
              docType: ["FTC_ORDER", "ORDER"],
              uploadDocType: "ORDER",
              uploadDocTypeName: "주문서",
              title: `주문서 첨부 — ${row.contract_no ?? ""}`,
            });
            setAttachDialogOpen(true);
          },
        };
      }
      if (col.key === "has_order_data") {
        return {
          ...col,
          onClick: (row) => {
            const cnt = Number(row.has_order_data ?? 0);
            if (!cnt || cnt <= 0) {
              toast.info("주문 라인이 입력되지 않았습니다.");
              return;
            }
            setOrderFormObjid(String(row.objid));
            setOrderFormOpen(true);
          },
        };
      }
      return col;
    }),
    []
  );

  const fetchList = useCallback(async () => {
    if (!user) return;
    setLoading(true);
    try {
      const params: Record<string, string> = {};
      Object.entries(searchForm).forEach(([k, v]) => { if (v) params[k] = v; });
      const data = await salesOrderMgmtApi.list(params);
      const mapped = data.map((r: any) => ({
        ...r,
        id: r.objid,
        paid_type_name: r.paid_type_name ?? PAID_TYPES[r.paid_type ?? ""] ?? "",
        contract_result_name: r.contract_result_name ?? r.contract_result ?? "",
        earliest_due_date_label: r.other_due_date_count && r.other_due_date_count > 0
          ? `${r.earliest_due_date} 외 ${r.other_due_date_count}건`
          : (r.earliest_due_date ?? ""),
      }));
      setRows(mapped);
    } catch { toast.error("주문서 목록 조회 실패"); }
    finally { setLoading(false); }
  }, [user, searchForm]);

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

  // ─── 하단 통계 ──────────────────────────────────────────────
  // 수주 건수 / 수주수량·취소 합계 / 공급가액·부가세·총액·원화총액 합계
  const orderSummary = useMemo(() => {
    const count = rows.length;
    const qtySum    = rows.reduce((acc, r) => acc + Number(r.order_quantity || 0), 0);
    const cancelSum = rows.reduce((acc, r) => acc + Number(r.cancel_qty_sum || 0), 0);
    const supplySum = rows.reduce((acc, r) => acc + Number(r.order_supply_price_sum || 0), 0);
    const vatSum    = rows.reduce((acc, r) => acc + Number(r.order_vat_sum || 0), 0);
    const totalSum  = rows.reduce((acc, r) => acc + Number(r.order_total_amount_sum || 0), 0);
    const krwSum    = rows.reduce((acc, r) => acc + Number(r.order_total_amount_krw || 0), 0);
    const money = (n: number) => n.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    const intFmt = (n: number) => n.toLocaleString();
    return [
      { label: "수주 건수", value: intFmt(count), suffix: "건" },
      { label: "수주수량 합계", value: intFmt(qtySum) },
      { label: "수주취소 합계", value: intFmt(cancelSum) },
      { label: "공급가액 합계", value: money(supplySum) },
      { label: "부가세 합계", value: money(vatSum) },
      { label: "총액 합계", value: money(totalSum) },
      { label: "원화총액 합계", value: money(krwSum) },
    ];
  }, [rows]);

  const openCreate = async () => {
    setDialogMode("create");
    const contractNo = await salesOrderMgmtApi.generateNumber().catch(() => "");
    setForm({
      contract_no: contractNo,
      contract_currency: "KRW",
      paid_type: "paid",
      order_date: new Date().toISOString().slice(0, 10),
      is_direct_order: "Y",
      items: [{ ...EMPTY_ITEM }],
    });
    setDialogOpen(true);
  };

  const openEdit = async () => {
    if (!selected) { toast.warning("수정할 주문서를 선택하세요."); return; }
    // wace 분기 (estimateAndOrderRegistFormPopup vs orderRegistFormPopup):
    //   is_direct_order = 'Y' → 직접등록 통합폼 (헤더 9개 + 라인 13컬럼)
    //   그 외('','N',null) → 견적요청에서 시작된 행 → 별도 수주등록 폼 (헤더 4개 + 라인 ORDER_*)
    if ((selected.is_direct_order ?? "") !== "Y") {
      setOrderRegistContract({ objid: selected.objid, contractNo: selected.contract_no ?? "" });
      setOrderRegistOpen(true);
      return;
    }
    setDialogMode("edit");
    try {
      const detail = await salesOrderMgmtApi.detail(selected.objid);
      setForm({
        objid: detail.objid,
        contract_no: detail.contract_no ?? "",
        category_cd: detail.category_cd ?? "",
        customer_objid: detail.customer_objid ?? "",
        product: detail.product ?? "",
        area_cd: detail.area_cd ?? "",
        paid_type: detail.paid_type ?? "paid",
        contract_currency: detail.contract_currency ?? "KRW",
        exchange_rate: detail.exchange_rate ?? "",
        receipt_date: detail.receipt_date ?? "",
        order_date: detail.order_date ?? "",
        approval_required: detail.approval_required ?? "N",
        is_direct_order: detail.is_direct_order ?? "Y",
        req_del_date: detail.req_del_date ?? "",
        po_no: detail.po_no ?? "",
        contract_result: detail.contract_result ?? "",
        pm_user_id: detail.pm_user_id ?? "",
        customer_request: detail.customer_request ?? "",
        shipping_method: detail.shipping_method ?? "",
        incoterms: detail.incoterms ?? "",
        items: (detail.items ?? []).map((it: any) => ({
          objid: it.objid,
          seq: it.seq,
          product: it.product ?? "",
          part_objid: it.part_objid ?? "",
          part_no: it.master_part_no ?? it.part_no ?? "",
          part_name: it.master_part_name ?? it.part_name ?? "",
          quantity: it.quantity ?? 1,
          due_date: it.due_date ?? "",
          return_reason: it.return_reason ?? "",
          customer_request: it.customer_request ?? "",
          order_quantity: it.order_quantity ?? "",
          order_unit_price: it.order_unit_price ?? "",
          order_supply_price: it.order_supply_price ?? "",
          order_vat: it.order_vat ?? "",
          order_total_amount: it.order_total_amount ?? "",
          cancel_qty: it.cancel_qty ?? "",
          serials: it.serials ?? [],
        })),
      });
      setDialogOpen(true);
    } catch { toast.error("주문서 상세 조회 실패"); }
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const items = (form.items ?? []).map((it) => {
        const oq = parseFloat((it.order_quantity ?? "0").replace(/,/g, "")) || 0;
        const up = parseFloat((it.order_unit_price ?? "0").replace(/,/g, "")) || 0;
        const supply = it.order_supply_price && it.order_supply_price !== "0" ? it.order_supply_price : String(oq * up);
        const vat = it.order_vat && it.order_vat !== "0" ? it.order_vat : String(Math.round(parseFloat(supply) * 0.1 * 100) / 100);
        const total = it.order_total_amount && it.order_total_amount !== "0" ? it.order_total_amount : String(parseFloat(supply) + parseFloat(vat));
        return { ...it, order_supply_price: supply, order_vat: vat, order_total_amount: total };
      });
      const payload = { ...form, items };
      if (dialogMode === "create") {
        await salesOrderMgmtApi.create(payload);
        toast.success("주문서가 등록되었습니다.");
      } else if (selected) {
        await salesOrderMgmtApi.update(selected.objid, payload);
        toast.success("주문서가 수정되었습니다.");
      }
      setDialogOpen(false);
      await fetchList();
    } catch (err: any) {
      toast.error(`저장 실패: ${err?.response?.data?.message ?? err.message}`);
    } finally { setSaving(false); }
  };

  const handleDelete = async () => {
    if (!selected) { toast.warning("삭제할 주문서를 선택하세요."); return; }
    const ok = await confirm("주문서 삭제", { description: `${selected.contract_no ?? selected.objid} 을(를) 삭제하시겠습니까?`, variant: "destructive" });
    if (!ok) return;
    try { await salesOrderMgmtApi.remove(selected.objid); toast.success("삭제되었습니다."); setSelected(null); await fetchList(); }
    catch (err: any) { toast.error(`삭제 실패: ${err?.response?.data?.message ?? err.message}`); }
  };

  // 수주확정 — wace 패턴: 행 1개만 선택 가능, 팝업에서 상태 선택 후 저장
  const handleConfirmOrder = () => {
    if (!selected) { toast.warning("수주확정할 행을 선택해주십시오."); return; }
    setConfirmStatusValue("");
    setConfirmStatusOpen(true);
  };
  const submitConfirmStatus = async () => {
    if (!selected) return;
    if (!confirmStatusValue) { toast.warning("수주상태를 선택해주세요."); return; }
    try {
      await salesOrderMgmtApi.setStatus(selected.objid, confirmStatusValue);
      toast.success("수주상태가 변경되었습니다.");
      setConfirmStatusOpen(false);
      await fetchList();
    } catch (err: any) {
      toast.error("수주확정 저장 중 오류가 발생했습니다.\n" + (err?.response?.data?.message ?? err.message ?? ""));
    }
  };

  // G4/G11 결재상신 — Amaranth SSO URL 발급 후 새 창 열기 (wace orderMgmtList.btnApproval 1:1)
  //   가드: 행 1건 선택 / 라인 0건 (hasOrderData) / 진행중·완료 상태 차단
  const handleAmaranthApproval = async () => {
    if (!selected) { toast.warning("결재상신할 행을 선택해주십시오."); return; }
    const hasOrderData = Number(selected.has_order_data ?? 0);
    if (hasOrderData === 0) { toast.warning("수주 품목을 먼저 등록해주세요."); return; }
    const amaranthStatus = String(selected.order_amaranth_status ?? "");
    if (amaranthStatus === "inProcess") { toast.warning("결재 진행중인 건은 상신할 수 없습니다."); return; }
    if (amaranthStatus === "complete")  { toast.warning("결재 완료된 건은 상신할 수 없습니다."); return; }
    const ok = await confirm("결재상신", { description: "결재상신 하시겠습니까?" });
    if (!ok) return;
    try {
      const { fullUrl } = await salesOrderMgmtApi.startApproval(selected.objid, {
        approvalTitle: `주문서 결재${selected.contract_no ? " - " + selected.contract_no : ""}`,
      });
      if (!fullUrl) { toast.error("결재 SSO URL을 받지 못했습니다."); return; }
      window.open(fullUrl, "amaranthApproval", "width=1200,height=900,scrollbars=yes,resizable=yes");
      await fetchList();
    } catch (err: any) {
      toast.error(err?.response?.data?.message ?? "결재 시스템 연동 중 오류가 발생했습니다.");
    }
  };

  // G9 수주복사 (wace orderMgmtList btnCopy 1:1)
  //   - 한 행만 선택 가능
  //   - 확인 다이얼로그 → POST /sales/order-mgmt/:id/copy
  //   - 성공 시 새 영업번호 안내 + 목록 새로고침 (복사본은 is_direct_order='Y'로 들어와 주문관리에 노출)
  const handleCopyOrder = async () => {
    if (!selected) { toast.warning("복사할 행을 선택해주십시오."); return; }
    const ok = await confirm("수주복사", {
      description: `[${selected.contract_no ?? selected.objid}] 수주를 복사하시겠습니까?`,
    });
    if (!ok) return;
    try {
      const { newContractNo } = await salesOrderMgmtApi.copyOrder(selected.objid);
      toast.success(`복사가 완료되었습니다. (영업번호: ${newContractNo})`);
      setSelected(null);
      await fetchList();
    } catch (err: any) {
      toast.error(err?.response?.data?.message ?? "복사 중 오류가 발생했습니다.");
    }
  };

  // 수주취소 — wace 패턴: 라인 조회 → 라인별 취소수량 input → 일괄 저장
  const handleCancelOrder = async () => {
    if (!selected) { toast.warning("수주취소할 행을 선택해주십시오."); return; }
    const orderQty = Number(selected.order_quantity ?? 0);
    if (orderQty === 0) { toast.warning("수주 수량이 없는 건은 취소할 수 없습니다."); return; }
    try {
      const detail = await salesOrderMgmtApi.detail(selected.objid);
      const items = (detail?.items ?? []) as any[];
      if (items.length === 0) { toast.warning("수주 품목 정보가 없습니다."); return; }
      setCancelLines(items.map((it) => ({
        objid: String(it.objid ?? ""),
        part_no: String(it.part_no ?? it.master_item_name ?? ""),
        part_name: String(it.part_name ?? ""),
        order_qty: parseInt(String(it.order_quantity ?? "0").replace(/,/g, ""), 10) || 0,
        cancel_qty: String(it.cancel_qty ?? ""),
      })));
      setCancelDialogOpen(true);
    } catch (err: any) {
      toast.error(err?.response?.data?.message ?? err.message);
    }
  };
  const updateCancelLine = (idx: number, val: string) => {
    setCancelLines((prev) => prev.map((l, i) => i === idx ? { ...l, cancel_qty: val } : l));
  };
  const submitCancelQty = async () => {
    if (!selected) return;
    // 클라이언트 측 사전 검증 (wace preConfirm)
    for (const l of cancelLines) {
      if (l.order_qty === 0) continue;
      const v = (l.cancel_qty ?? "").trim();
      if (v === "") continue;
      const n = parseInt(v, 10);
      if (Number.isNaN(n) || n < 0) { toast.warning("취소 수량은 0 이상이어야 합니다."); return; }
      if (n >= l.order_qty) { toast.warning(`취소 수량(${n})은 수주수량(${l.order_qty})보다 적어야 합니다.`); return; }
    }
    setCancelSaving(true);
    try {
      const entries = cancelLines.map((l) => ({
        itemObjId: l.objid,
        cancelQty: l.cancel_qty ?? "",
        orderQty: String(l.order_qty),
      }));
      const res = await salesOrderMgmtApi.saveCancelQty(selected.objid, entries);
      toast.success(res?.message ?? "수주취소 수량이 저장되었습니다.");
      setCancelDialogOpen(false);
      await fetchList();
    } catch (err: any) {
      toast.error(err?.response?.data?.message ?? "수주취소 저장 중 오류가 발생했습니다.");
    } finally {
      setCancelSaving(false);
    }
  };

  const updateItem = (idx: number, key: keyof OrderItem, val: any) => {
    setForm((prev) => {
      const items = [...(prev.items ?? [])];
      (items[idx] as any)[key] = val;
      return { ...prev, items };
    });
  };

  // wace fn_calculateItemAmount / fn_calculateFromSupplyPrice / fn_calculateTotalFromVat 이식
  //   수량 또는 단가 변경 → 공급가액 = 수량×단가, 부가세 = round(공급가액×0.1), 총액 = 공급가액+부가세
  //   공급가액 직접 입력 → 부가세 = round(supply×0.1), 총액 = supply+vat
  //   부가세 직접 입력 → 총액 = supply+vat 재계산만
  //   총액 직접 입력 → 다른 값 영향 없음
  const toNum = (v: any) => Number(String(v ?? "0").replace(/,/g, "")) || 0;
  const updateItemWithCalc = (idx: number, key: keyof OrderItem, val: any) => {
    setForm((prev) => {
      const items = [...(prev.items ?? [])];
      const cur: any = { ...items[idx], [key]: val };
      if (key === "order_quantity" || key === "order_unit_price") {
        const supply = toNum(cur.order_quantity) * toNum(cur.order_unit_price);
        const vat = Math.round(supply * 0.1);
        cur.order_supply_price = String(supply);
        cur.order_vat = String(vat);
        cur.order_total_amount = String(supply + vat);
      } else if (key === "order_supply_price") {
        const supply = toNum(cur.order_supply_price);
        const vat = Math.round(supply * 0.1);
        cur.order_vat = String(vat);
        cur.order_total_amount = String(supply + vat);
      } else if (key === "order_vat") {
        cur.order_total_amount = String(toNum(cur.order_supply_price) + toNum(cur.order_vat));
      }
      items[idx] = cur;
      return { ...prev, items };
    });
  };
  const addItem = () => setForm((prev) => ({ ...prev, items: [...(prev.items ?? []), { ...EMPTY_ITEM, seq: (prev.items?.length ?? 0) + 1 }] }));
  const removeItem = (idx: number) => setForm((prev) => ({ ...prev, items: (prev.items ?? []).filter((_, i) => i !== idx).map((it, i) => ({ ...it, seq: i + 1 })) }));

  // S/N 관리 (wace fn_openItemSnPopup) — 견적관리와 동일 패턴
  const openSerialDialog = (idx: number) => {
    const item = form.items?.[idx];
    setSerialDialogIdx(idx);
    setSerialDraft([...(item?.serials ?? [])]);
    setSerialInput("");
    setSerialDialogOpen(true);
  };
  const addSerialDraft = () => {
    const v = serialInput.trim();
    if (!v) { toast.warning("S/N을 입력해주세요."); return; }
    if (serialDraft.includes(v)) { toast.warning("이미 등록된 S/N입니다."); return; }
    setSerialDraft((prev) => [...prev, v]);
    setSerialInput("");
  };
  const removeSerialDraft = (i: number) => setSerialDraft((prev) => prev.filter((_, k) => k !== i));
  const applySerialDraft = () => {
    if (serialDialogIdx === null) return;
    updateItem(serialDialogIdx, "serials", [...serialDraft]);
    setSerialDialogOpen(false);
  };
  const openSeqDialog = () => { setSeqStartNo(""); setSeqCount(""); setSeqDialogOpen(true); };
  const generateSequentialSn = () => {
    const startNo = seqStartNo.trim();
    const count = parseInt(seqCount, 10);
    if (!startNo) { toast.warning("시작 번호를 입력해주세요."); return; }
    if (!count || count < 1) { toast.warning("생성 개수를 1 이상 입력해주세요."); return; }
    if (count > 100) { toast.warning("최대 100개까지만 생성 가능합니다."); return; }
    const m = startNo.match(/^(.*?)(\d+)$/);
    if (!m) { toast.warning("형식이 올바르지 않습니다. 마지막에 숫자가 있어야 합니다."); return; }
    const prefix = m[1]; const startNum = parseInt(m[2], 10); const numLen = m[2].length;
    setSerialDraft((prev) => {
      const next = [...prev];
      for (let i = 0; i < count; i++) {
        const sn = prefix + String(startNum + i).padStart(numLen, "0");
        if (!next.includes(sn)) next.push(sn);
      }
      return next;
    });
    setSeqDialogOpen(false);
  };

  // 라인 합계 자동 계산용 헬퍼
  const formatNum = (v: any) => {
    const n = Number(String(v ?? "0").replace(/,/g, ""));
    return isNaN(n) ? 0 : n;
  };
  const lineTotal = useMemo(() => {
    const items = form.items ?? [];
    return items.reduce((acc, it) => ({
      qty:    acc.qty    + formatNum(it.order_quantity),
      supply: acc.supply + formatNum(it.order_supply_price),
      vat:    acc.vat    + formatNum(it.order_vat),
      total:  acc.total  + formatNum(it.order_total_amount),
    }), { qty: 0, supply: 0, vat: 0, total: 0 });
  }, [form.items]);

  const handleReset = () => setSearchForm({
    category_cd: "", search_poNo: "", customer_objid: "",
    search_partObjId: "", search_partName: "", search_serialNo: "", contract_result: "",
    order_start_date: "", order_end_date: "",
    due_start_date: "", due_end_date: "",
  });

  return (
    <div className="flex h-full flex-col overflow-hidden p-2 gap-2">
      {ConfirmDialogComponent}

      <PageHeader
        loading={loading}
        onSearch={fetchList}
        onReset={handleReset}
        actions={
        <>
          <Button size="sm" className="h-8 gap-1 text-xs" onClick={() => { if (selected) openEdit(); else openCreate(); }}>
            {selected ? <Pencil className="h-3.5 w-3.5" /> : <Plus className="h-3.5 w-3.5" />}
            {selected ? "수주수정" : "수주입력"}
          </Button>
          <Button size="sm" className="h-8 gap-1 bg-emerald-600 hover:bg-emerald-700 text-white text-xs" onClick={handleConfirmOrder} disabled={!selected}>
            <CheckCircle2 className="h-3.5 w-3.5" />수주확정
          </Button>
          <Button size="sm" className="h-8 gap-1 bg-rose-600 hover:bg-rose-700 text-white text-xs" onClick={handleCancelOrder} disabled={!selected}>
            <XCircle className="h-3.5 w-3.5" />수주취소
          </Button>
          <Button size="sm" variant="outline" className="h-8 gap-1 text-xs" onClick={handleCopyOrder} disabled={!selected}>
            <Copy className="h-3.5 w-3.5" />수주복사
          </Button>
          <Button size="sm" className="h-8 gap-1 bg-sky-600 hover:bg-sky-700 text-white text-xs" onClick={handleAmaranthApproval} disabled={!selected}>
            <Send className="h-3.5 w-3.5" />결재상신
          </Button>
          <Button size="sm" variant="destructive" className="h-8 gap-1 text-xs" onClick={handleDelete} disabled={!selected}>
            <Trash2 className="h-3.5 w-3.5" />삭제
          </Button>
        </>
      } />

      <CompactFilterBar totalText={<>총 {rows.length.toLocaleString()}건</>}>
        <CompactFilterField label="주문유형" width={130}>
          <CommCodeSelect groupId="0000167"
            value={searchForm.category_cd}
            onValueChange={(v) => setSearchForm({ ...searchForm, category_cd: v })} />
        </CompactFilterField>
        <CompactFilterField label="발주번호" width={140}>
          <Input placeholder="발주번호 검색"
                 value={searchForm.search_poNo}
                 onChange={(e) => setSearchForm({ ...searchForm, search_poNo: e.target.value })} />
        </CompactFilterField>
        <CompactFilterField label="고객사" width={160}>
          <CustomerSelect
            value={searchForm.customer_objid}
            onValueChange={(v) => setSearchForm({ ...searchForm, customer_objid: v })} />
        </CompactFilterField>
        <CompactFilterField label="품번" width={130}>
          <PartSelect mode="partNo"
            value={searchForm.search_partObjId}
            onValueChange={(v) => setSearchForm({ ...searchForm, search_partObjId: v })} />
        </CompactFilterField>
        <CompactFilterField label="품명" width={150}>
          <PartSelect mode="partName"
            value={searchForm.search_partObjId}
            onValueChange={(v) => setSearchForm({ ...searchForm, search_partObjId: v })} />
        </CompactFilterField>
        <CompactFilterField label="S/N" width={120}>
          <Input value={searchForm.search_serialNo}
                 onChange={(e) => setSearchForm({ ...searchForm, search_serialNo: e.target.value })} />
        </CompactFilterField>
        <CompactFilterField label="수주상태" width={130}>
          <CommCodeSelect groupId="0000963"
            value={searchForm.contract_result}
            onValueChange={(v) => setSearchForm({ ...searchForm, contract_result: v })} />
        </CompactFilterField>
        <CompactFilterField label="발주일" width={280}>
          <CompactDateRange
            from={searchForm.order_start_date}
            setFrom={(v) => setSearchForm({ ...searchForm, order_start_date: v })}
            to={searchForm.order_end_date}
            setTo={(v) => setSearchForm({ ...searchForm, order_end_date: v })}
          />
        </CompactFilterField>
        <CompactFilterField label="요청납기" width={280}>
          <CompactDateRange
            from={searchForm.due_start_date}
            setFrom={(v) => setSearchForm({ ...searchForm, due_start_date: v })}
            to={searchForm.due_end_date}
            setTo={(v) => setSearchForm({ ...searchForm, due_end_date: v })}
          />
        </CompactFilterField>
      </CompactFilterBar>

      <DataGrid
        gridId="sales-order"
        columns={gridColumns}
        data={rows}
        showCheckbox
        checkedIds={selected ? [selected.objid] : []}
        onCheckedChange={(ids) => {
          // wace 패턴: 다중 선택 가능하나 액션 시 1개 검증. 여기선 마지막 1개만 selected에 반영해 단일 흐름 유지
          if (ids.length === 0) { setSelected(null); return; }
          const last = ids[ids.length - 1];
          setSelected(rows.find((r) => r.id === last) ?? null);
        }}
        selectedId={selected ? selected.objid : null}
        onSelect={(id) => setSelected(id ? rows.find((r) => r.id === id) ?? null : null)}
        onRowDoubleClick={(row) => { setSelected(row); openEdit(); }}
        emptyMessage={loading ? "조회 중..." : "데이터가 없습니다"}
        loading={loading}
        showColumnSettings
        paginationStyle="range"
        pageSizeOptions={[10, 15, 20, 50, 100]}
        summaryStats={orderSummary}
        systemColumnKeys={["writer_name"]}
        onRefresh={fetchList}
        onDownload={() => {
          if (rows.length === 0) { toast.info("내보낼 데이터가 없습니다."); return; }
          const exportRows = rows.map((r) => {
            const out: Record<string, any> = {};
            GRID_COLUMNS.forEach((col) => { out[col.label] = r[col.key] ?? ""; });
            return out;
          });
          exportToExcel(exportRows, "주문관리.xlsx", "주문관리");
        }}
        showChart
      />

      <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
        <DialogContent
          className="!max-w-[95vw] w-[95vw] max-h-[92vh] overflow-y-auto"
          onInteractOutside={(e) => e.preventDefault()}  /* 자식 S/N·연속번호 Dialog 닫힐 때 부모까지 닫히는 현상 차단 */
        >
          <DialogHeader>
            <DialogTitle>
              {/* 이 통합폼은 항상 is_direct_order='Y' 케이스만 처리 (wace estimateAndOrderRegistFormPopup) */}
              영업관리 _ 주문서관리 _ 수주통합{dialogMode === "edit" ? "수정" : "등록"}
            </DialogTitle>
            <DialogDescription className="sr-only">수주통합 기본정보 + 품목정보를 입력합니다. (wace estimateAndOrderRegistFormPopup 1:1)</DialogDescription>
          </DialogHeader>

          {/* 수주통합 기본정보 — wace 헤더 9개 (영업번호 자동채번 표시 포함) */}
          <fieldset className="border rounded-md p-3">
            <legend className="text-sm font-semibold px-2">수주통합 기본정보</legend>
            <div className="grid grid-cols-4 gap-3">
              <div>
                <Label className="text-xs">영업번호 (자동채번)</Label>
                <Input readOnly className="bg-muted/30" value={form.contract_no ?? ""} placeholder="저장 시 자동 부여" />
              </div>
              <div>
                <Label className="text-xs">주문유형 <span className="text-rose-600">*</span></Label>
                <CommCodeSelect groupId="0000167" value={form.category_cd ?? ""}
                  onValueChange={(v) => setForm({ ...form, category_cd: v })} />
              </div>
              <div>
                <Label className="text-xs">국내/해외 <span className="text-rose-600">*</span></Label>
                <CommCodeSelect groupId="0001219" value={form.area_cd ?? ""}
                  onValueChange={(v) => setForm({ ...form, area_cd: v })} />
              </div>
              <div>
                <Label className="text-xs">고객사 <span className="text-rose-600">*</span></Label>
                <CustomerSelect value={form.customer_objid ?? ""}
                  onValueChange={(v) => setForm({ ...form, customer_objid: v })} />
              </div>
              <div>
                <Label className="text-xs">유/무상 <span className="text-rose-600">*</span></Label>
                <Select value={form.paid_type || undefined}
                        onValueChange={(v) => setForm({ ...form, paid_type: v })}>
                  <SelectTrigger><SelectValue placeholder="선택" /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="paid">유상</SelectItem>
                    <SelectItem value="free">무상</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div>
                <Label className="text-xs">접수일 <span className="text-rose-600">*</span></Label>
                <Input type="date" value={form.receipt_date ?? ""}
                       onChange={(e) => setForm({ ...form, receipt_date: e.target.value })} />
              </div>
              <div>
                <Label className="text-xs">견적환종</Label>
                <CommCodeSelect groupId="0001533" value={form.contract_currency ?? ""}
                  onValueChange={(v) => setForm({ ...form, contract_currency: v })} />
              </div>
              <div>
                <Label className="text-xs">견적환율</Label>
                <Input value={form.exchange_rate ?? ""}
                       onChange={(e) => setForm({ ...form, exchange_rate: e.target.value })} />
              </div>
              <div>
                <Label className="text-xs">발주번호</Label>
                <Input value={form.po_no ?? ""}
                       onChange={(e) => setForm({ ...form, po_no: e.target.value })} />
              </div>
              <div>
                <Label className="text-xs">발주일 <span className="text-rose-600">*</span></Label>
                <Input type="date" value={form.order_date ?? ""}
                       onChange={(e) => setForm({ ...form, order_date: e.target.value })} />
              </div>
            </div>
          </fieldset>

          {/* 품목정보 — wace 13컬럼 + Total 합계 행 */}
          <fieldset className="border rounded-md p-3 space-y-2">
            <legend className="text-sm font-semibold px-2 flex items-center justify-between w-full">
              <span>품목정보</span>
            </legend>
            <div className="overflow-x-auto">
              <table className="w-full text-xs">
                <thead className="bg-muted/50">
                  <tr>
                    <th className="p-2 w-10 whitespace-nowrap">No</th>
                    <th className="p-2 w-28 whitespace-nowrap">제품구분 <span className="text-rose-600">*</span></th>
                    <th className="p-2 w-40 whitespace-nowrap">품번 <span className="text-rose-600">*</span></th>
                    <th className="p-2 w-56 whitespace-nowrap">품명 <span className="text-rose-600">*</span></th>
                    <th className="p-2 w-40 whitespace-nowrap">S/N</th>
                    <th className="p-2 w-36 whitespace-nowrap">요청납기</th>
                    <th className="p-2 min-w-[220px] whitespace-nowrap">고객요청사항</th>
                    <th className="p-2 w-28 whitespace-nowrap">반납사유</th>
                    <th className="p-2 w-24 whitespace-nowrap text-right">수주수량 <span className="text-rose-600">*</span></th>
                    <th className="p-2 w-28 whitespace-nowrap text-right">수주단가</th>
                    <th className="p-2 w-32 whitespace-nowrap text-right">수주공급가액</th>
                    <th className="p-2 w-28 whitespace-nowrap text-right">수주부가세</th>
                    <th className="p-2 w-32 whitespace-nowrap text-right">수주총액</th>
                    <th className="p-2 w-12 whitespace-nowrap">삭제</th>
                  </tr>
                </thead>
                <tbody>
                  {(form.items ?? []).map((it, idx) => (
                    <tr key={idx} className="border-t">
                      <td className="p-1 text-center">{it.seq}</td>
                      <td className="p-1">
                        <CommCodeSelect groupId="0000001"
                          value={it.product ?? ""}
                          onValueChange={(v) => updateItem(idx, "product", v)} />
                      </td>
                      <td className="p-1">
                        <PartSelect mode="partNo" value={it.part_objid}
                          onValueChange={(partObjId, row) => {
                            setForm((prev) => {
                              const items = [...(prev.items ?? [])];
                              items[idx] = { ...items[idx], part_objid: partObjId,
                                part_no: row?.item_number ?? "",
                                part_name: row?.item_name ?? items[idx].part_name };
                              return { ...prev, items };
                            });
                          }} />
                      </td>
                      <td className="p-1">
                        <PartSelect mode="partName" value={it.part_objid}
                          onValueChange={(partObjId, row) => {
                            setForm((prev) => {
                              const items = [...(prev.items ?? [])];
                              items[idx] = { ...items[idx], part_objid: partObjId,
                                part_no: row?.item_number ?? items[idx].part_no,
                                part_name: row?.item_name ?? "" };
                              return { ...prev, items };
                            });
                          }} />
                      </td>
                      <td className="p-1">
                        <Input className="h-8" readOnly
                               value={(it.serials ?? []).join(", ")}
                               onClick={() => openSerialDialog(idx)}
                               placeholder="클릭하여 S/N 추가" />
                      </td>
                      <td className="p-1">
                        <Input className="h-8" type="date" value={it.due_date ?? ""}
                               onChange={(e) => updateItem(idx, "due_date", e.target.value)} />
                      </td>
                      <td className="p-1">
                        <Textarea className="min-h-[34px] resize-y text-xs" rows={1}
                                  value={it.customer_request ?? ""}
                                  onChange={(e) => updateItem(idx, "customer_request", e.target.value)} />
                      </td>
                      <td className="p-1">
                        <CommCodeSelect groupId="0001810"
                          value={it.return_reason ?? ""}
                          onValueChange={(v) => updateItem(idx, "return_reason", v)} />
                      </td>
                      <td className="p-1">
                        <Input className="h-8 text-right" type="number" min={0}
                               value={it.order_quantity ?? ""}
                               onChange={(e) => updateItemWithCalc(idx, "order_quantity", e.target.value)} />
                      </td>
                      <td className="p-1"><Input className="h-8 text-right" value={it.order_unit_price ?? ""}
                             onChange={(e) => updateItemWithCalc(idx, "order_unit_price", e.target.value)} /></td>
                      <td className="p-1"><Input className="h-8 text-right" value={it.order_supply_price ?? ""}
                             onChange={(e) => updateItemWithCalc(idx, "order_supply_price", e.target.value)} /></td>
                      <td className="p-1"><Input className="h-8 text-right" value={it.order_vat ?? ""}
                             onChange={(e) => updateItemWithCalc(idx, "order_vat", e.target.value)} /></td>
                      <td className="p-1"><Input className="h-8 text-right" value={it.order_total_amount ?? ""}
                             onChange={(e) => updateItem(idx, "order_total_amount", e.target.value)} /></td>
                      <td className="p-1 text-center">
                        <Button variant="ghost" size="icon" onClick={() => removeItem(idx)}>
                          <Trash2 className="w-3 h-3" />
                        </Button>
                      </td>
                    </tr>
                  ))}
                  {(!form.items || form.items.length === 0) && (
                    <tr><td colSpan={14} className="p-3 text-center text-muted-foreground">품목이 없습니다.</td></tr>
                  )}
                </tbody>
                {(form.items?.length ?? 0) > 0 && (
                  <tfoot>
                    <tr className="bg-muted/30 font-semibold">
                      <td colSpan={8} className="p-2 text-center">Total</td>
                      <td className="p-2 text-right">{lineTotal.qty.toLocaleString()}</td>
                      <td className="p-2"></td>
                      <td className="p-2 text-right">{lineTotal.supply.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</td>
                      <td className="p-2 text-right">{lineTotal.vat.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</td>
                      <td className="p-2 text-right">{lineTotal.total.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</td>
                      <td className="p-2"></td>
                    </tr>
                  </tfoot>
                )}
              </table>
            </div>
            <div className="flex gap-2">
              <Button size="sm" variant="outline" onClick={addItem}>
                <Plus className="w-3 h-3 mr-1" />품목 추가
              </Button>
            </div>
          </fieldset>

          <DialogFooter>
            <Button variant="outline" onClick={() => setDialogOpen(false)} disabled={saving}>취소</Button>
            <Button onClick={handleSave} disabled={saving}>
              {saving ? <Loader2 className="w-4 h-4 mr-1 animate-spin" /> : <Save className="w-4 h-4 mr-1" />}저장
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* S/N 관리 — wace fn_openItemSnPopup */}
      <Dialog open={serialDialogOpen} onOpenChange={setSerialDialogOpen}>
        <DialogContent className="max-w-2xl" onInteractOutside={(e) => e.preventDefault()}>
          <DialogHeader>
            <DialogTitle className="text-center">S/N 관리</DialogTitle>
            <DialogDescription className="sr-only">시리얼 번호 추가/삭제 및 연속번호 생성</DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="max-h-[300px] overflow-y-auto border rounded">
              <table className="w-full text-sm">
                <thead className="bg-muted/50">
                  <tr>
                    <th className="border px-3 py-2 w-16 text-center">번호</th>
                    <th className="border px-3 py-2 text-center">S/N</th>
                    <th className="border px-3 py-2 w-20 text-center">삭제</th>
                  </tr>
                </thead>
                <tbody>
                  {serialDraft.length === 0 ? (
                    <tr><td colSpan={3} className="border px-3 py-8 text-center text-muted-foreground">등록된 S/N이 없습니다.</td></tr>
                  ) : serialDraft.map((s, i) => (
                    <tr key={i}>
                      <td className="border px-3 py-1.5 text-center">{i + 1}</td>
                      <td className="border px-3 py-1.5">{s}</td>
                      <td className="border px-3 py-1.5 text-center">
                        <Button size="sm" variant="outline" onClick={() => removeSerialDraft(i)}>삭제</Button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div className="flex gap-2">
              <Input value={serialInput} onChange={(e) => setSerialInput(e.target.value)}
                     onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addSerialDraft(); } }}
                     placeholder="S/N 입력" />
              <Button onClick={addSerialDraft} type="button">추가</Button>
            </div>
          </div>
          <DialogFooter className="sm:justify-center">
            <Button variant="outline" onClick={openSeqDialog}>연속번호생성</Button>
            <Button onClick={applySerialDraft}>확인</Button>
            <Button variant="outline" onClick={() => setSerialDialogOpen(false)}>취소</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 연속번호 생성 — wace fn_openItemSequentialSnPopup */}
      <Dialog open={seqDialogOpen} onOpenChange={setSeqDialogOpen}>
        <DialogContent className="max-w-sm" onInteractOutside={(e) => e.preventDefault()}>
          <DialogHeader>
            <DialogTitle>연속번호 생성</DialogTitle>
            <DialogDescription className="sr-only">시작번호와 생성개수로 연속 S/N 일괄 추가</DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <div>
              <Label className="text-xs">시작번호 <span className="text-rose-600">*</span></Label>
              <Input value={seqStartNo} onChange={(e) => setSeqStartNo(e.target.value)} placeholder="예: ITEM-001" />
            </div>
            <div>
              <Label className="text-xs">생성개수 <span className="text-rose-600">*</span></Label>
              <Input type="number" min={1} max={100} value={seqCount}
                     onChange={(e) => setSeqCount(e.target.value)} placeholder="예: 10" />
            </div>
            <div className="bg-muted/40 rounded p-2 text-[11px] leading-5 text-muted-foreground">
              예: ITEM-001, 개수 3 → ITEM-001, ITEM-002, ITEM-003<br />
              ※ 최대 100개까지 생성 가능
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setSeqDialogOpen(false)}>취소</Button>
            <Button onClick={generateSequentialSn}>생성</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 첨부파일 다이얼로그 — 주문서첨부 클립 컬럼 클릭 시 */}
      {attachContext && (
        <AttachmentDialog
          open={attachDialogOpen}
          onOpenChange={setAttachDialogOpen}
          targetObjid={attachContext.targetObjid}
          docType={attachContext.docType}
          uploadDocType={attachContext.uploadDocType}
          uploadDocTypeName={attachContext.uploadDocTypeName}
          title={attachContext.title}
          onChanged={fetchList}
        />
      )}

      {/* 주문서 자동생성 뷰 — 주문서 폴더 컬럼 클릭 시 (wace orderFormView 대응) */}
      <OrderFormViewDialog
        open={orderFormOpen}
        onOpenChange={setOrderFormOpen}
        objid={orderFormObjid}
      />

      {/* 견적요청에서 시작된 행의 수주등록 다이얼로그 (wace orderRegistFormPopup 1:1) */}
      <OrderRegistDialog
        open={orderRegistOpen}
        onOpenChange={setOrderRegistOpen}
        contractObjId={orderRegistContract?.objid ?? null}
        contractNo={orderRegistContract?.contractNo ?? null}
        onSaved={() => { setOrderRegistOpen(false); fetchList(); }}
      />

      {/* 수주확정 — wace fn_openOrderConfirmPopup 이식: 상태 select */}
      <Dialog open={confirmStatusOpen} onOpenChange={setConfirmStatusOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>수주확정</DialogTitle>
            <DialogDescription className="sr-only">변경할 수주상태를 선택합니다.</DialogDescription>
          </DialogHeader>
          <div className="space-y-3 py-2">
            <div className="text-sm">
              <span className="font-semibold">현재 수주상태: </span>
              <span>{selected?.contract_result ? (CONTRACT_RESULTS.find(o => o.value === selected.contract_result)?.label ?? selected.contract_result) : "-"}</span>
            </div>
            <div>
              <Label className="text-xs mb-1 block">변경할 수주상태 <span className="text-rose-600">*</span></Label>
              <Select value={confirmStatusValue || undefined} onValueChange={setConfirmStatusValue}>
                <SelectTrigger><SelectValue placeholder="선택" /></SelectTrigger>
                <SelectContent>
                  {CONTRACT_RESULTS.filter((o) => o.value).map((o) => (
                    <SelectItem key={o.value} value={o.value}>{o.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setConfirmStatusOpen(false)}>취소</Button>
            <Button onClick={submitConfirmStatus}>확정</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 수주취소 — wace fn_openOrderCancelPopup 이식: 라인별 cancel_qty input */}
      <Dialog open={cancelDialogOpen} onOpenChange={setCancelDialogOpen}>
        <DialogContent className="max-w-3xl">
          <DialogHeader>
            <DialogTitle>수주취소 수량 입력</DialogTitle>
            <DialogDescription className="sr-only">라인별 취소 수량을 입력합니다. 전체 수량 취소는 불가합니다.</DialogDescription>
          </DialogHeader>
          <div className="max-h-[400px] overflow-y-auto">
            <table className="w-full text-sm border">
              <thead className="bg-muted/50">
                <tr>
                  <th className="border px-2 py-2 w-32">품번</th>
                  <th className="border px-2 py-2">품명</th>
                  <th className="border px-2 py-2 w-24 text-right">수주수량</th>
                  <th className="border px-2 py-2 w-32 text-center">취소수량</th>
                </tr>
              </thead>
              <tbody>
                {cancelLines.map((l, idx) => (
                  <tr key={idx}>
                    <td className="border px-2 py-1 text-center">{l.part_no}</td>
                    <td className="border px-2 py-1">{l.part_name}</td>
                    <td className="border px-2 py-1 text-right">{l.order_qty > 0 ? l.order_qty.toLocaleString() : "-"}</td>
                    <td className="border px-2 py-1 text-center">
                      {l.order_qty > 0 ? (
                        <Input
                          type="number"
                          min={0}
                          max={l.order_qty - 1}
                          value={l.cancel_qty}
                          onChange={(e) => updateCancelLine(idx, e.target.value)}
                          className="h-8 text-right"
                          placeholder="0"
                        />
                      ) : (
                        <span className="text-muted-foreground">-</span>
                      )}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          <p className="text-xs text-muted-foreground">※ 전체 수량 취소는 불가하며, 부분 수량만 취소 가능합니다.</p>
          <DialogFooter>
            <Button variant="outline" onClick={() => setCancelDialogOpen(false)}>닫기</Button>
            <Button className="bg-rose-600 hover:bg-rose-700 text-white" onClick={submitCancelQty} disabled={cancelSaving}>
              {cancelSaving ? <Loader2 className="w-4 h-4 mr-1 animate-spin" /> : null}저장
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 품목 검색 — 등록 다이얼로그 (다중 선택) */}
      <ItemSearchDialog
        open={itemDialogOpen}
        onOpenChange={setItemDialogOpen}
        onSelect={(items: ItemRow[]) => {
          setForm((prev) => {
            const startSeq = (prev.items?.length ?? 0) + 1;
            const newItems: OrderItem[] = items.map((it, idx) => ({
              seq: startSeq + idx,
              part_objid: String(it.objid ?? ""),
              part_no: it.item_number ?? it.item_code ?? "",
              part_name: it.item_name ?? "",
              quantity: 1,
              order_quantity: "1",
              order_unit_price: String(it.selling_price ?? it.standard_price ?? "0"),
              order_supply_price: "0",
              order_vat: "0",
              order_total_amount: "0",
            }));
            return { ...prev, items: [...(prev.items ?? []), ...newItems] };
          });
          toast.success(`${items.length}건 품목 추가`);
        }}
      />
    </div>
  );
}
