"use client";

/**
 * 판매품목정보 — 하드코딩 페이지
 *
 * 좌측: 판매품목 목록 (item_info, 판매 관련 필터)
 * 우측: 선택한 품목의 거래처 정보 (customer_item_mapping → customer_mng 조인)
 *
 * 거래처관리와 양방향 연동 (같은 customer_item_mapping 테이블)
 */

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 { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import { Plus, Trash2, Save, Loader2, FileSpreadsheet, Download, Pencil, Package, Users, Search, X, 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";

const ITEM_TABLE = "item_info";
const MAPPING_TABLE = "customer_item_mapping";
const CUSTOMER_TABLE = "customer_mng";

// 좌측: 판매품목 컬럼
const LEFT_COLUMNS: DataGridColumn[] = [
  { key: "item_number", label: "품번", width: "w-[110px]" },
  { key: "item_name", label: "품명", minWidth: "min-w-[130px]" },
  { key: "size", label: "규격", width: "w-[90px]" },
  { key: "unit", label: "단위", width: "w-[60px]" },
  { key: "standard_price", label: "기준단가", width: "w-[90px]", formatNumber: true, align: "right" },
  { key: "selling_price", label: "판매가격", width: "w-[90px]", formatNumber: true, align: "right" },
  { key: "currency_code", label: "통화", width: "w-[50px]" },
  { key: "status", label: "상태", width: "w-[60px]" },
];

// 우측: 거래처 정보 컬럼
const RIGHT_COLUMNS: DataGridColumn[] = [
  { key: "customer_code", label: "거래처코드", width: "w-[110px]" },
  { key: "customer_name", label: "거래처명", minWidth: "min-w-[120px]" },
  { key: "customer_item_code", label: "거래처품번", width: "w-[100px]" },
  { key: "customer_item_name", label: "거래처품명", width: "w-[100px]" },
  { key: "base_price", label: "기준가", width: "w-[80px]", formatNumber: true, align: "right" },
  { key: "calculated_price", label: "단가", width: "w-[80px]", formatNumber: true, align: "right" },
  { key: "currency_code", label: "통화", width: "w-[50px]" },
];

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

  // 좌측: 품목
  const [items, setItems] = useState<any[]>([]);
  const [itemLoading, setItemLoading] = useState(false);
  const [itemCount, setItemCount] = useState(0);
  const [searchFilters, setSearchFilters] = useState<FilterValue[]>([]);
  const [selectedItemId, setSelectedItemId] = useState<string | null>(null);

  // 테이블 설정
  const [tableSettingsOpen, setTableSettingsOpen] = useState(false);
  const [filterConfig, setFilterConfig] = useState<TableSettings["filters"] | undefined>();

  // 우측: 거래처
  const [customerItems, setCustomerItems] = useState<any[]>([]);
  const [customerLoading, setCustomerLoading] = useState(false);
  const [customerCheckedIds, setCustomerCheckedIds] = useState<string[]>([]);

  // 카테고리
  const [categoryOptions, setCategoryOptions] = useState<Record<string, { code: string; label: string; isDefault?: boolean }[]>>({});

  // 거래처 추가 모달
  const [custSelectOpen, setCustSelectOpen] = useState(false);
  const [custSearchKeyword, setCustSearchKeyword] = useState("");
  const [custSearchResults, setCustSearchResults] = useState<any[]>([]);
  const [custSearchLoading, setCustSearchLoading] = useState(false);
  const [custCheckedIds, setCustCheckedIds] = useState<Set<string>>(new Set());

  // 품목 수정 모달
  const [editItemOpen, setEditItemOpen] = useState(false);
  const [editItemForm, setEditItemForm] = useState<Record<string, any>>({});
  const [saving, setSaving] = useState(false);

  // 엑셀
  const [excelUploadOpen, setExcelUploadOpen] = useState(false);

  // 거래처 상세 입력 모달 (거래처 품번/품명 + 단가)
  const [custDetailOpen, setCustDetailOpen] = useState(false);
  const [selectedCustsForDetail, setSelectedCustsForDetail] = useState<any[]>([]);
  const [custMappings, setCustMappings] = useState<Record<string, Array<{ _id: string; customer_item_code: string; customer_item_name: string }>>>({});
  const [custPrices, setCustPrices] = useState<Record<string, Array<{
    _id: string; start_date: string; end_date: string; currency_code: string;
    base_price_type: string; base_price: string; discount_type: string;
    discount_value: string; rounding_type: string; rounding_unit_value: string;
    calculated_price: string;
  }>>>({});
  const [priceCategoryOptions, setPriceCategoryOptions] = useState<Record<string, { code: string; label: string }[]>>({});
  const [editCustData, setEditCustData] = useState<any>(null);

  // 테이블 설정 적용 (필터)
  const applyTableSettings = useCallback((settings: TableSettings) => {
    setFilterConfig(settings.filters);
  }, []);

  // 마운트 시 저장된 설정 복원
  useEffect(() => {
    const saved = loadTableSettings("sales-item");
    if (saved) applyTableSettings(saved);
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  // 카테고리 로드
  useEffect(() => {
    const load = async () => {
      const optMap: Record<string, { code: string; label: string; isDefault?: boolean }[]> = {};
      const flatten = (vals: any[]): { code: string; label: string; isDefault?: boolean }[] => {
        const result: { code: string; label: string; isDefault?: boolean }[] = [];
        for (const v of vals) {
          result.push({ code: v.valueCode, label: v.valueLabel, isDefault: v.isDefault });
          if (v.children?.length) result.push(...flatten(v.children));
        }
        return result;
      };
      for (const col of ["unit", "material", "division", "type", "status", "inventory_unit", "currency_code", "user_type01", "user_type02"]) {
        try {
          const res = await apiClient.get(`/table-categories/${ITEM_TABLE}/${col}/values`);
          if (res.data?.success) optMap[col] = flatten(res.data.data || []);
        } catch { /* skip */ }
      }
      setCategoryOptions(optMap);

      // 단가 카테고리
      const priceOpts: Record<string, { code: string; label: string }[]> = {};
      for (const col of ["base_price_type", "currency_code", "discount_type", "rounding_type", "rounding_unit_value"]) {
        try {
          const res = await apiClient.get(`/table-categories/customer_item_prices/${col}/values`);
          if (res.data?.success) priceOpts[col] = flatten(res.data.data || []);
        } catch { /* skip */ }
      }
      setPriceCategoryOptions(priceOpts);
    };
    load();
  }, []);

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

  // 좌측: 품목 조회
  const fetchItems = useCallback(async () => {
    setItemLoading(true);
    try {
      const filters: { columnName: string; operator: string; value: any }[] = searchFilters.map((f) => ({ columnName: f.columnName, operator: f.operator, value: f.value }));

      // 판매품목/영업관리 division 필터 (다중값 컬럼이므로 contains로 매칭)
      filters.push({ columnName: "division", operator: "contains", value: "CAT_ML8ZFVEL_1TOR" });

      const res = await apiClient.post(`/table-management/tables/${ITEM_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 || [];
      const CATS = ["unit", "material", "division", "type", "status", "inventory_unit", "currency_code", "user_type01", "user_type02"];
      const data = raw.map((r: any) => {
        const converted = { ...r };
        for (const col of CATS) {
          if (converted[col]) converted[col] = resolve(col, converted[col]);
        }
        return converted;
      });
      setItems(data);
      setItemCount(res.data?.data?.total || raw.length);
    } catch (err) {
      console.error("품목 조회 실패:", err);
      toast.error("품목 목록을 불러오는데 실패했습니다.");
    } finally {
      setItemLoading(false);
    }
  }, [searchFilters, categoryOptions]);

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

  // 선택된 품목
  const selectedItem = items.find((i) => i.id === selectedItemId);

  // 우측: 거래처 목록 조회
  useEffect(() => {
    if (!selectedItem?.item_number) { setCustomerItems([]); setCustomerCheckedIds([]); return; }
    setCustomerCheckedIds([]);
    const itemKey = selectedItem.item_number;
    const fetchCustomerItems = async () => {
      setCustomerLoading(true);
      try {
        // 1. customer_item_mapping에서 해당 품목의 매핑 조회
        const mapRes = await apiClient.post(`/table-management/tables/${MAPPING_TABLE}/data`, {
          page: 1, size: 500,
          dataFilter: { enabled: true, filters: [{ columnName: "item_id", operator: "equals", value: itemKey }] },
          autoFilter: true,
        });
        const mappings = mapRes.data?.data?.data || mapRes.data?.data?.rows || [];

        // 2. customer_id → customer_mng 조인 (거래처명)
        const custIds = [...new Set(mappings.map((m: any) => m.customer_id).filter(Boolean))];
        let custMap: Record<string, any> = {};
        if (custIds.length > 0) {
          try {
            const custRes = await apiClient.post(`/table-management/tables/${CUSTOMER_TABLE}/data`, {
              page: 1, size: custIds.length + 10,
              dataFilter: { enabled: true, filters: [{ columnName: "customer_code", operator: "in", value: custIds }] },
              autoFilter: true,
            });
            for (const c of (custRes.data?.data?.data || custRes.data?.data?.rows || [])) {
              custMap[c.customer_code] = c;
            }
          } catch { /* skip */ }
        }

        // 3. customer_item_prices 조회 (단가 정보)
        let allPrices: any[] = [];
        if (mappings.length > 0) {
          try {
            const priceRes = await apiClient.post(`/table-management/tables/customer_item_prices/data`, {
              page: 1, size: 500,
              dataFilter: { enabled: true, filters: [
                { columnName: "item_id", operator: "equals", value: itemKey },
              ]},
              autoFilter: true,
            });
            allPrices = priceRes.data?.data?.data || priceRes.data?.data?.rows || [];
          } catch { /* skip */ }
        }

        // 4. 거래처별 중복 제거 + 오늘 날짜 기준 단가 매칭
        const priceResolve = (col: string, code: string) => {
          if (!code) return "";
          return priceCategoryOptions[col]?.find((o: any) => o.code === code)?.label || code;
        };
        const today = new Date().toISOString().split("T")[0];
        const seenCustIds = new Set<string>();

        // customer_id로 정렬하여 같은 거래처끼리 묶기
        const sortedMappings = [...mappings].sort((a: any, b: any) => (a.customer_id || "").localeCompare(b.customer_id || ""));

        setCustomerItems(sortedMappings.map((m: any) => {
          const custKey = m.customer_id || "";
          const isFirstOfGroup = !seenCustIds.has(custKey);
          if (custKey) seenCustIds.add(custKey);

          // 오늘 날짜에 해당하는 단가
          const custPriceList = allPrices.filter((p: any) => p.customer_id === custKey);
          const todayPrice = custPriceList.find((p: any) =>
            (!p.start_date || p.start_date <= today) && (!p.end_date || p.end_date >= today)
          ) || custPriceList[0] || {};

          return {
            ...m,
            customer_code: isFirstOfGroup ? custKey : "",
            customer_name: isFirstOfGroup ? (custMap[custKey]?.customer_name || "") : "",
            customer_item_code: m.customer_item_code || "",
            customer_item_name: m.customer_item_name || "",
            base_price: todayPrice.base_price || "",
            calculated_price: todayPrice.calculated_price || todayPrice.unit_price || "",
            currency_code: priceResolve("currency_code", todayPrice.currency_code || ""),
          };
        }));
      } catch (err) {
        console.error("거래처 조회 실패:", err);
      } finally {
        setCustomerLoading(false);
      }
    };
    fetchCustomerItems();
  }, [selectedItem?.item_number, priceCategoryOptions]);

  // 거래처 검색
  const searchCustomers = async () => {
    setCustSearchLoading(true);
    try {
      const filters: any[] = [];
      if (custSearchKeyword) filters.push({ columnName: "customer_name", operator: "contains", value: custSearchKeyword });
      const res = await apiClient.post(`/table-management/tables/${CUSTOMER_TABLE}/data`, {
        page: 1, size: 50,
        dataFilter: filters.length > 0 ? { enabled: true, filters } : undefined,
        autoFilter: true,
      });
      const all = res.data?.data?.data || res.data?.data?.rows || [];
      // 이미 등록된 거래처 제외
      const existing = new Set(customerItems.map((c: any) => c.customer_id || c.customer_code));
      setCustSearchResults(all.filter((c: any) => !existing.has(c.customer_code)));
    } catch { /* skip */ } finally { setCustSearchLoading(false); }
  };

  // 거래처 선택 → 상세 모달로 이동
  const goToCustDetail = () => {
    const selected = custSearchResults.filter((c) => custCheckedIds.has(c.id));
    if (selected.length === 0) { toast.error("거래처를 선택해주세요."); return; }
    setSelectedCustsForDetail(selected);
    const mappings: typeof custMappings = {};
    const prices: typeof custPrices = {};
    for (const cust of selected) {
      const key = cust.customer_code || cust.id;
      mappings[key] = [];
      prices[key] = [{
        _id: `p_${Date.now()}_${Math.random()}`,
        start_date: "", end_date: "", currency_code: "CAT_MLAMDKVN_PZJI",
        base_price_type: "CAT_MLAMFGFT_4RZW", base_price: selectedItem?.standard_price || selectedItem?.selling_price || "",
        discount_type: "", discount_value: "", rounding_type: "", rounding_unit_value: "",
        calculated_price: selectedItem?.standard_price || selectedItem?.selling_price || "",
      }];
    }
    setCustMappings(mappings);
    setCustPrices(prices);
    setCustSelectOpen(false);
    setCustDetailOpen(true);
  };

  const addMappingRow = (custKey: string) => {
    setCustMappings((prev) => ({
      ...prev,
      [custKey]: [...(prev[custKey] || []), { _id: `m_${Date.now()}_${Math.random()}`, customer_item_code: "", customer_item_name: "" }],
    }));
  };

  const removeMappingRow = (custKey: string, rowId: string) => {
    setCustMappings((prev) => ({
      ...prev,
      [custKey]: (prev[custKey] || []).filter((r) => r._id !== rowId),
    }));
  };

  const updateMappingRow = (custKey: string, rowId: string, field: string, value: string) => {
    setCustMappings((prev) => ({
      ...prev,
      [custKey]: (prev[custKey] || []).map((r) => r._id === rowId ? { ...r, [field]: value } : r),
    }));
  };

  const addPriceRow = (custKey: string) => {
    setCustPrices((prev) => ({
      ...prev,
      [custKey]: [...(prev[custKey] || []), {
        _id: `p_${Date.now()}_${Math.random()}`,
        start_date: "", end_date: "", currency_code: "CAT_MLAMDKVN_PZJI",
        base_price_type: "CAT_MLAMFGFT_4RZW", base_price: "",
        discount_type: "", discount_value: "", rounding_type: "", rounding_unit_value: "",
        calculated_price: "",
      }],
    }));
  };

  const removePriceRow = (custKey: string, rowId: string) => {
    setCustPrices((prev) => ({
      ...prev,
      [custKey]: (prev[custKey] || []).filter((r) => r._id !== rowId),
    }));
  };

  const updatePriceRow = (custKey: string, rowId: string, field: string, value: string) => {
    setCustPrices((prev) => ({
      ...prev,
      [custKey]: (prev[custKey] || []).map((r) => {
        if (r._id !== rowId) return r;
        const updated = { ...r, [field]: value };
        if (["base_price", "discount_type", "discount_value"].includes(field)) {
          const bp = Number(updated.base_price) || 0;
          const dv = Number(updated.discount_value) || 0;
          const dt = updated.discount_type;
          let calc = bp;
          if (dt === "CAT_MLAMBEC8_URQA") calc = bp * (1 - dv / 100);
          else if (dt === "CAT_MLAMBLFM_JTLO") calc = bp - dv;
          updated.calculated_price = String(Math.round(calc));
        }
        return updated;
      }),
    }));
  };

  const openEditCust = async (row: any) => {
    const custKey = row.customer_code || row.customer_id;

    // customer_mng에서 거래처 정보 조회
    let custInfo: any = { customer_code: custKey, customer_name: row.customer_name || "" };
    try {
      const res = await apiClient.post(`/table-management/tables/customer_mng/data`, {
        page: 1, size: 1,
        dataFilter: { enabled: true, filters: [{ columnName: "customer_code", operator: "equals", value: custKey }] },
        autoFilter: true,
      });
      const found = (res.data?.data?.data || res.data?.data?.rows || [])[0];
      if (found) custInfo = found;
    } catch { /* skip */ }

    const mappingRows = [{
      _id: `m_existing_${row.id}`,
      customer_item_code: row.customer_item_code || "",
      customer_item_name: row.customer_item_name || "",
    }].filter((m) => m.customer_item_code || m.customer_item_name);

    const priceRows = [{
      _id: `p_existing_${row.id}`,
      start_date: row.start_date || "",
      end_date: row.end_date || "",
      currency_code: row.currency_code || "CAT_MLAMDKVN_PZJI",
      base_price_type: row.base_price_type || "CAT_MLAMFGFT_4RZW",
      base_price: row.base_price ? String(row.base_price) : "",
      discount_type: row.discount_type || "",
      discount_value: row.discount_value ? String(row.discount_value) : "",
      rounding_type: row.rounding_type || "",
      rounding_unit_value: row.rounding_unit_value || "",
      calculated_price: row.calculated_price ? String(row.calculated_price) : "",
    }].filter((p) => p.base_price || p.start_date);

    if (priceRows.length === 0) {
      priceRows.push({
        _id: `p_${Date.now()}`, start_date: "", end_date: "", currency_code: "CAT_MLAMDKVN_PZJI",
        base_price_type: "CAT_MLAMFGFT_4RZW", base_price: "", discount_type: "", discount_value: "",
        rounding_type: "", rounding_unit_value: "", calculated_price: "",
      });
    }

    setSelectedCustsForDetail([custInfo]);
    setCustMappings({ [custKey]: mappingRows });
    setCustPrices({ [custKey]: priceRows });
    setEditCustData(row);
    setCustDetailOpen(true);
  };

  const handleCustDetailSave = async () => {
    if (!selectedItem) return;
    const isEditingExisting = !!editCustData;
    setSaving(true);
    try {
      for (const cust of selectedCustsForDetail) {
        const custKey = cust.customer_code || cust.id;
        const mappingRows = custMappings[custKey] || [];

        if (isEditingExisting && editCustData?.id) {
          await apiClient.put(`/table-management/tables/${MAPPING_TABLE}/edit`, {
            originalData: { id: editCustData.id },
            updatedData: {
              customer_item_code: mappingRows[0]?.customer_item_code || "",
              customer_item_name: mappingRows[0]?.customer_item_name || "",
            },
          });

          // 기존 prices 삭제 후 재등록
          try {
            const existingPrices = await apiClient.post(`/table-management/tables/customer_item_prices/data`, {
              page: 1, size: 100,
              dataFilter: { enabled: true, filters: [
                { columnName: "mapping_id", operator: "equals", value: editCustData.id },
              ]}, autoFilter: true,
            });
            const existing = existingPrices.data?.data?.data || existingPrices.data?.data?.rows || [];
            if (existing.length > 0) {
              await apiClient.delete(`/table-management/tables/customer_item_prices/delete`, {
                data: existing.map((p: any) => ({ id: p.id })),
              });
            }
          } catch { /* skip */ }

          const priceRows = (custPrices[custKey] || []).filter((p) =>
            (p.base_price && Number(p.base_price) > 0) || p.start_date
          );
          for (const price of priceRows) {
            await apiClient.post(`/table-management/tables/customer_item_prices/add`, {
              mapping_id: editCustData.id,
              customer_id: custKey,
              item_id: selectedItem.item_number,
              start_date: price.start_date || null, end_date: price.end_date || null,
              currency_code: price.currency_code || null, base_price_type: price.base_price_type || null,
              base_price: price.base_price ? Number(price.base_price) : null,
              discount_type: price.discount_type || null, discount_value: price.discount_value ? Number(price.discount_value) : null,
              rounding_type: price.rounding_type || null, rounding_unit_value: price.rounding_unit_value || null,
              calculated_price: price.calculated_price ? Number(price.calculated_price) : null,
            });
          }
        } else {
          // 신규 등록
          const mappingRes = await apiClient.post(`/table-management/tables/${MAPPING_TABLE}/add`, {
            customer_id: custKey, item_id: selectedItem.item_number,
            customer_item_code: mappingRows[0]?.customer_item_code || "",
            customer_item_name: mappingRows[0]?.customer_item_name || "",
          });
          const mappingId = mappingRes.data?.data?.id || null;

          for (let mi = 1; mi < mappingRows.length; mi++) {
            await apiClient.post(`/table-management/tables/${MAPPING_TABLE}/add`, {
              customer_id: custKey, item_id: selectedItem.item_number,
              customer_item_code: mappingRows[mi].customer_item_code || "",
              customer_item_name: mappingRows[mi].customer_item_name || "",
            });
          }

          const priceRows = (custPrices[custKey] || []).filter((p) =>
            (p.base_price && Number(p.base_price) > 0) || p.start_date
          );
          for (const price of priceRows) {
            await apiClient.post(`/table-management/tables/customer_item_prices/add`, {
              mapping_id: mappingId || "", customer_id: custKey, item_id: selectedItem.item_number,
              start_date: price.start_date || null, end_date: price.end_date || null,
              currency_code: price.currency_code || null, base_price_type: price.base_price_type || null,
              base_price: price.base_price ? Number(price.base_price) : null,
              discount_type: price.discount_type || null, discount_value: price.discount_value ? Number(price.discount_value) : null,
              rounding_type: price.rounding_type || null, rounding_unit_value: price.rounding_unit_value || null,
              calculated_price: price.calculated_price ? Number(price.calculated_price) : null,
            });
          }
        }
      }
      toast.success(isEditingExisting ? "수정되었습니다." : `${selectedCustsForDetail.length}개 거래처가 추가되었습니다.`);
      setCustDetailOpen(false);
      setEditCustData(null);
      setCustCheckedIds(new Set());
      // 우측 새로고침
      const sid = selectedItemId;
      setSelectedItemId(null);
      setTimeout(() => setSelectedItemId(sid), 50);
    } catch (err: any) {
      toast.error(err.response?.data?.message || "저장에 실패했습니다.");
    } finally {
      setSaving(false);
    }
  };

  // 품목 수정
  const openEditItem = () => {
    if (!selectedItem) return;
    setEditItemForm({ ...selectedItem });
    setEditItemOpen(true);
  };

  const handleEditSave = async () => {
    if (!editItemForm.id) return;
    setSaving(true);
    try {
      await apiClient.put(`/table-management/tables/${ITEM_TABLE}/edit`, {
        originalData: { id: editItemForm.id },
        updatedData: {
          selling_price: editItemForm.selling_price || null,
          standard_price: editItemForm.standard_price || null,
          currency_code: editItemForm.currency_code || null,
        },
      });
      toast.success("수정되었습니다.");
      setEditItemOpen(false);
      fetchItems();
    } catch (err: any) {
      toast.error(err.response?.data?.message || "수정에 실패했습니다.");
    } finally {
      setSaving(false);
    }
  };

  // 우측: 거래처 매핑 삭제
  const handleCustomerMappingDelete = async () => {
    if (customerCheckedIds.length === 0) return;
    const ok = await confirm(`선택한 ${customerCheckedIds.length}개 거래처 매핑을 삭제하시겠습니까?`, {
      description: "관련된 단가 정보도 함께 삭제됩니다.",
      variant: "destructive", confirmText: "삭제",
    });
    if (!ok) return;
    try {
      // 관련 단가 삭제
      for (const mappingId of customerCheckedIds) {
        try {
          const priceRes = await apiClient.post(`/table-management/tables/customer_item_prices/data`, {
            page: 1, size: 500,
            dataFilter: { enabled: true, filters: [{ columnName: "mapping_id", operator: "equals", value: mappingId }] },
            autoFilter: true,
          });
          const prices = priceRes.data?.data?.data || priceRes.data?.data?.rows || [];
          if (prices.length > 0) {
            await apiClient.delete(`/table-management/tables/customer_item_prices/delete`, {
              data: prices.map((p: any) => ({ id: p.id })),
            });
          }
        } catch { /* skip */ }
      }
      // 매핑 삭제
      await apiClient.delete(`/table-management/tables/${MAPPING_TABLE}/delete`, {
        data: customerCheckedIds.map((id) => ({ id })),
      });
      toast.success(`${customerCheckedIds.length}개 거래처 매핑이 삭제되었습니다.`);
      setCustomerCheckedIds([]);
      // 우측 새로고침
      const sid = selectedItemId;
      setSelectedItemId(null);
      setTimeout(() => setSelectedItemId(sid), 50);
    } catch {
      toast.error("삭제에 실패했습니다.");
    }
  };

  // 엑셀 다운로드
  const handleExcelDownload = async () => {
    if (items.length === 0) return;
    const data = items.map((i) => ({
      품번: i.item_number, 품명: i.item_name, 규격: i.size, 단위: i.unit,
      기준단가: i.standard_price, 판매가격: i.selling_price, 통화: i.currency_code, 상태: i.status,
    }));
    await exportToExcel(data, "판매품목정보.xlsx", "판매품목");
    toast.success("다운로드 완료");
  };

  return (
    <div className="flex h-full flex-col gap-3 p-3">
      {/* 검색 */}
      <DynamicSearchFilter
        tableName={ITEM_TABLE}
        filterId="sales-item"
        onFilterChange={setSearchFilters}
        dataCount={itemCount}
        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" onClick={() => setExcelUploadOpen(true)}>
              <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={55} minSize={30}>
            <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">
                  <Package className="w-4 h-4" /> 판매품목 목록
                  <Badge variant="secondary" className="font-normal">{itemCount}건</Badge>
                </div>
                <div className="flex gap-1.5">
                  <Button variant="outline" size="sm" disabled={!selectedItemId} onClick={openEditItem}>
                    <Pencil className="w-3.5 h-3.5 mr-1" /> 수정
                  </Button>
                </div>
              </div>
              <DataGrid
                gridId="sales-item-left"
                columns={LEFT_COLUMNS}
                data={items}
                loading={itemLoading}
                selectedId={selectedItemId}
                onSelect={setSelectedItemId}
                onRowDoubleClick={() => openEditItem()}
                emptyMessage="등록된 판매품목이 없습니다"
              />
            </div>
          </ResizablePanel>

          <ResizableHandle withHandle />

          {/* 우측: 거래처 정보 */}
          <ResizablePanel defaultSize={45} 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">
                  <Users className="w-4 h-4" /> 거래처 정보
                  {selectedItem && <Badge variant="outline" className="font-normal">{selectedItem.item_name}</Badge>}
                </div>
                <div className="flex gap-1.5">
                  <Button variant="outline" size="sm" disabled={!selectedItemId}
                    onClick={() => { setCustCheckedIds(new Set()); setCustSelectOpen(true); searchCustomers(); }}>
                    <Plus className="w-3.5 h-3.5 mr-1" /> 거래처 추가
                  </Button>
                  <Button variant="destructive" size="sm" disabled={customerCheckedIds.length === 0}
                    onClick={handleCustomerMappingDelete}>
                    <Trash2 className="w-3.5 h-3.5 mr-1" /> 삭제
                  </Button>
                </div>
              </div>
              {!selectedItemId ? (
                <div className="flex-1 flex items-center justify-center text-muted-foreground text-sm">
                  좌측에서 품목을 선택하세요
                </div>
              ) : (
                <DataGrid
                  gridId="sales-item-right"
                  columns={RIGHT_COLUMNS}
                  data={customerItems}
                  loading={customerLoading}
                  showRowNumber={false}
                  showCheckbox
                  checkedIds={customerCheckedIds}
                  onCheckedChange={setCustomerCheckedIds}
                  emptyMessage="등록된 거래처가 없습니다"
                  onRowDoubleClick={(row) => openEditCust(row)}
                />
              )}
            </div>
          </ResizablePanel>
        </ResizablePanelGroup>
      </div>

      {/* 품목 수정 모달 */}
      <FullscreenDialog
        open={editItemOpen}
        onOpenChange={setEditItemOpen}
        title="판매품목 수정"
        description={`${editItemForm.item_number || ""} — ${editItemForm.item_name || ""}`}
        defaultMaxWidth="max-w-2xl"
        footer={
          <>
            <Button variant="outline" onClick={() => setEditItemOpen(false)}>취소</Button>
            <Button onClick={handleEditSave} 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">
          {/* 품목 기본정보 (읽기 전용) */}
          {[
            { key: "item_number", label: "품목코드" },
            { key: "item_name", label: "품명" },
            { key: "size", label: "규격" },
            { key: "unit", label: "단위" },
            { key: "material", label: "재질" },
            { key: "status", label: "상태" },
          ].map((f) => (
            <div key={f.key} className="space-y-1.5">
              <Label className="text-sm text-muted-foreground">{f.label}</Label>
              <Input value={editItemForm[f.key] || ""} className="h-9 bg-muted/50" disabled />
            </div>
          ))}

          <div className="col-span-2 border-t my-2" />

          {/* 판매 설정 (수정 가능) */}
          <div className="space-y-1.5">
            <Label className="text-sm">판매가격</Label>
            <Input value={editItemForm.selling_price || ""} onChange={(e) => setEditItemForm((p) => ({ ...p, selling_price: e.target.value }))}
              placeholder="판매가격" className="h-9" />
          </div>
          <div className="space-y-1.5">
            <Label className="text-sm">기준단가</Label>
            <Input value={editItemForm.standard_price || ""} onChange={(e) => setEditItemForm((p) => ({ ...p, standard_price: e.target.value }))}
              placeholder="기준단가" className="h-9" />
          </div>
          <div className="space-y-1.5">
            <Label className="text-sm">통화</Label>
            <Select value={editItemForm.currency_code || ""} onValueChange={(v) => setEditItemForm((p) => ({ ...p, currency_code: v }))}>
              <SelectTrigger className="h-9"><SelectValue placeholder="통화" /></SelectTrigger>
              <SelectContent>
                {(categoryOptions["currency_code"] || []).map((o) => <SelectItem key={o.code} value={o.code}>{o.label}</SelectItem>)}
              </SelectContent>
            </Select>
          </div>
        </div>
      </FullscreenDialog>

      {/* 거래처 추가 모달 */}
      <Dialog open={custSelectOpen} onOpenChange={setCustSelectOpen}>
        <DialogContent className="max-w-2xl max-h-[70vh]">
          <DialogHeader>
            <DialogTitle>거래처 선택</DialogTitle>
            <DialogDescription>품목에 추가할 거래처를 선택하세요.</DialogDescription>
          </DialogHeader>
          <div className="flex gap-2 mb-3">
            <Input placeholder="거래처명 검색" value={custSearchKeyword}
              onChange={(e) => setCustSearchKeyword(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && searchCustomers()}
              className="h-9 flex-1" />
            <Button size="sm" onClick={searchCustomers} disabled={custSearchLoading} className="h-9">
              {custSearchLoading ? <Loader2 className="w-4 h-4 animate-spin" /> : <><Search className="w-4 h-4 mr-1" /> 조회</>}
            </Button>
          </div>
          <div className="overflow-auto max-h-[350px] border rounded-lg">
            <Table>
              <TableHeader className="sticky top-0 bg-background z-10">
                <TableRow>
                  <TableHead className="w-[40px] text-center">
                    <input type="checkbox"
                      checked={custSearchResults.length > 0 && custCheckedIds.size === custSearchResults.length}
                      onChange={(e) => {
                        if (e.target.checked) setCustCheckedIds(new Set(custSearchResults.map((c) => c.id)));
                        else setCustCheckedIds(new Set());
                      }} />
                  </TableHead>
                  <TableHead className="w-[110px]">거래처코드</TableHead>
                  <TableHead className="min-w-[130px]">거래처명</TableHead>
                  <TableHead className="w-[80px]">거래유형</TableHead>
                  <TableHead className="w-[80px]">담당자</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {custSearchResults.length === 0 ? (
                  <TableRow><TableCell colSpan={5} className="text-center text-muted-foreground py-8">검색 결과가 없습니다</TableCell></TableRow>
                ) : custSearchResults.map((c) => (
                  <TableRow key={c.id} className={cn("cursor-pointer", custCheckedIds.has(c.id) && "bg-primary/5")}
                    onClick={() => setCustCheckedIds((prev) => {
                      const next = new Set(prev);
                      if (next.has(c.id)) next.delete(c.id); else next.add(c.id);
                      return next;
                    })}>
                    <TableCell className="text-center"><input type="checkbox" checked={custCheckedIds.has(c.id)} readOnly /></TableCell>
                    <TableCell className="text-xs">{c.customer_code}</TableCell>
                    <TableCell className="text-sm">{c.customer_name}</TableCell>
                    <TableCell className="text-xs">{c.division}</TableCell>
                    <TableCell className="text-xs">{c.contact_person}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
          <DialogFooter>
            <div className="flex items-center gap-2 w-full justify-between">
              <span className="text-sm text-muted-foreground">{custCheckedIds.size}개 선택됨</span>
              <div className="flex gap-2">
                <Button variant="outline" onClick={() => setCustSelectOpen(false)}>취소</Button>
                <Button onClick={goToCustDetail} disabled={custCheckedIds.size === 0}>
                  <Plus className="w-4 h-4 mr-1" /> {custCheckedIds.size}개 다음
                </Button>
              </div>
            </div>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 거래처 상세 입력/수정 모달 */}
      <FullscreenDialog
        open={custDetailOpen}
        onOpenChange={setCustDetailOpen}
        title={`📋 거래처 상세정보 ${editCustData ? "수정" : "입력"} — ${selectedItem?.item_name || ""}`}
        description={editCustData ? "거래처 품번/품명과 기간별 단가를 수정합니다." : "선택한 거래처의 품번/품명과 기간별 단가를 설정합니다."}
        defaultMaxWidth="max-w-[1100px]"
        footer={
          <>
            <Button variant="outline" onClick={() => {
              setCustDetailOpen(false);
              if (!editCustData) setCustSelectOpen(true);
              setEditCustData(null);
            }}>{editCustData ? "취소" : "← 이전"}</Button>
            <Button onClick={handleCustDetailSave} 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="space-y-6 py-2">
          {selectedCustsForDetail.map((cust, idx) => {
            const custKey = cust.customer_code || cust.id;
            const mappingRows = custMappings[custKey] || [];
            const prices = custPrices[custKey] || [];

            return (
              <div key={custKey} className="border rounded-xl overflow-hidden bg-card">
                <div className="px-5 py-3 bg-muted/30 border-b">
                  <div className="font-bold">{idx + 1}. {cust.customer_name || custKey}</div>
                  <div className="text-xs text-muted-foreground">{custKey}</div>
                </div>

                <div className="flex gap-4 p-4">
                  {/* 좌: 거래처 품번/품명 */}
                  <div className="flex-1 border rounded-lg p-4 bg-blue-50/30 dark:bg-blue-950/10">
                    <div className="flex items-center justify-between mb-3">
                      <span className="text-sm font-semibold">거래처 품번/품명 관리</span>
                      <Button variant="outline" size="sm" className="h-7 text-xs" onClick={() => addMappingRow(custKey)}>
                        <Plus className="h-3 w-3 mr-1" /> 품번 추가
                      </Button>
                    </div>
                    <div className="space-y-2">
                      {mappingRows.length === 0 ? (
                        <div className="text-xs text-muted-foreground py-2">입력된 거래처 품번이 없습니다</div>
                      ) : mappingRows.map((mRow, mIdx) => (
                        <div key={mRow._id} className="flex gap-2 items-center">
                          <span className="text-xs text-muted-foreground w-4 shrink-0">{mIdx + 1}</span>
                          <Input value={mRow.customer_item_code}
                            onChange={(e) => updateMappingRow(custKey, mRow._id, "customer_item_code", e.target.value)}
                            placeholder="거래처 품번" className="h-8 text-sm flex-1" />
                          <Input value={mRow.customer_item_name}
                            onChange={(e) => updateMappingRow(custKey, mRow._id, "customer_item_name", e.target.value)}
                            placeholder="거래처 품명" className="h-8 text-sm flex-1" />
                          <Button variant="ghost" size="sm" className="h-7 w-7 p-0 text-destructive shrink-0"
                            onClick={() => removeMappingRow(custKey, mRow._id)}>
                            <X className="h-3 w-3" />
                          </Button>
                        </div>
                      ))}
                    </div>
                  </div>

                  {/* 우: 기간별 단가 */}
                  <div className="flex-1 border rounded-lg p-4 bg-amber-50/30 dark:bg-amber-950/10">
                    <div className="flex items-center justify-between mb-3">
                      <span className="text-sm font-semibold">기간별 단가 설정</span>
                      <Button variant="outline" size="sm" className="h-7 text-xs" onClick={() => addPriceRow(custKey)}>
                        <Plus className="h-3 w-3 mr-1" /> 단가 추가
                      </Button>
                    </div>
                    <div className="space-y-3">
                      {prices.map((price, pIdx) => (
                        <div key={price._id} className="border rounded-lg p-3 bg-background space-y-2">
                          <div className="flex items-center justify-between">
                            <span className="text-xs font-medium text-muted-foreground">단가 {pIdx + 1}</span>
                            {prices.length > 1 && (
                              <Button variant="ghost" size="sm" className="h-6 w-6 p-0 text-destructive"
                                onClick={() => removePriceRow(custKey, price._id)}>
                                <X className="h-3 w-3" />
                              </Button>
                            )}
                          </div>
                          <div className="flex gap-2 items-center">
                            <div className="flex-1">
                              <FormDatePicker value={price.start_date}
                                onChange={(v) => updatePriceRow(custKey, price._id, "start_date", v)} placeholder="시작일" />
                            </div>
                            <span className="text-xs text-muted-foreground">~</span>
                            <div className="flex-1">
                              <FormDatePicker value={price.end_date}
                                onChange={(v) => updatePriceRow(custKey, price._id, "end_date", v)} placeholder="종료일" />
                            </div>
                            <div className="w-[80px]">
                              <Select value={price.currency_code} onValueChange={(v) => updatePriceRow(custKey, price._id, "currency_code", v)}>
                                <SelectTrigger className="h-8 text-xs"><SelectValue placeholder="통화" /></SelectTrigger>
                                <SelectContent>
                                  {(priceCategoryOptions["currency_code"] || []).map((o) => <SelectItem key={o.code} value={o.code}>{o.label}</SelectItem>)}
                                </SelectContent>
                              </Select>
                            </div>
                          </div>
                          <div className="flex gap-2 items-center">
                            <div className="w-[90px]">
                              <Select value={price.base_price_type} onValueChange={(v) => updatePriceRow(custKey, price._id, "base_price_type", v)}>
                                <SelectTrigger className="h-8 text-xs"><SelectValue placeholder="기준" /></SelectTrigger>
                                <SelectContent>
                                  {(priceCategoryOptions["base_price_type"] || []).map((o) => <SelectItem key={o.code} value={o.code}>{o.label}</SelectItem>)}
                                </SelectContent>
                              </Select>
                            </div>
                            <Input value={price.base_price}
                              onChange={(e) => updatePriceRow(custKey, price._id, "base_price", e.target.value)}
                              className="h-8 text-xs text-right flex-1" placeholder="기준가" />
                            <div className="w-[90px]">
                              <Select value={price.discount_type} onValueChange={(v) => updatePriceRow(custKey, price._id, "discount_type", v)}>
                                <SelectTrigger className="h-8 text-xs"><SelectValue placeholder="할인" /></SelectTrigger>
                                <SelectContent>
                                  <SelectItem value="none">할인없음</SelectItem>
                                  {(priceCategoryOptions["discount_type"] || []).map((o) => <SelectItem key={o.code} value={o.code}>{o.label}</SelectItem>)}
                                </SelectContent>
                              </Select>
                            </div>
                            <Input value={price.discount_value}
                              onChange={(e) => updatePriceRow(custKey, price._id, "discount_value", e.target.value)}
                              className="h-8 text-xs text-right w-[60px]" placeholder="0" />
                            <div className="w-[90px]">
                              <Select value={price.rounding_unit_value} onValueChange={(v) => updatePriceRow(custKey, price._id, "rounding_unit_value", v)}>
                                <SelectTrigger className="h-8 text-xs"><SelectValue placeholder="반올림" /></SelectTrigger>
                                <SelectContent>
                                  {(priceCategoryOptions["rounding_unit_value"] || []).map((o) => <SelectItem key={o.code} value={o.code}>{o.label}</SelectItem>)}
                                </SelectContent>
                              </Select>
                            </div>
                          </div>
                          <div className="flex items-center justify-end gap-2 pt-1 border-t">
                            <span className="text-xs text-muted-foreground">계산 단가:</span>
                            <span className="font-bold text-sm">{price.calculated_price ? Number(price.calculated_price).toLocaleString() : "-"}</span>
                          </div>
                        </div>
                      ))}
                    </div>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </FullscreenDialog>

      {/* 엑셀 업로드 */}
      <ExcelUploadModal
        open={excelUploadOpen}
        onOpenChange={setExcelUploadOpen}
        tableName={ITEM_TABLE}
        userId={user?.userId}
        onSuccess={() => fetchItems()}
      />

      {ConfirmDialogComponent}

      <TableSettingsModal
        open={tableSettingsOpen}
        onOpenChange={setTableSettingsOpen}
        tableName={ITEM_TABLE}
        settingsId="sales-item"
        onSave={applyTableSettings}
      />
    </div>
  );
}
