"use client";

import React, { useEffect, useState, useCallback, useMemo, useRef } from "react";
import { ComponentRendererProps } from "@/types/component";
import {
  Loader2,
  Package,
  TrendingUp,
  Warehouse,
  CheckCircle,
  Factory,
  Truck,
  Plus,
  X,
} from "lucide-react";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { toast } from "sonner";
import {
  ShippingPlanEditorConfig,
  ItemGroup,
  PlanDetailRow,
  ItemAggregation,
} from "./types";
import { getShippingPlanAggregate, batchSaveShippingPlans } from "@/lib/api/shipping";

export interface ShippingPlanEditorComponentProps
  extends ComponentRendererProps {}

export const ShippingPlanEditorComponent: React.FC<
  ShippingPlanEditorComponentProps
> = ({ component, isDesignMode = false, groupedData, formData, onFormDataChange, onClose, ...props }) => {
  const config = (component?.componentConfig ||
    {}) as ShippingPlanEditorConfig;
  const [itemGroups, setItemGroups] = useState<ItemGroup[]>([]);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [source, setSource] = useState<"master" | "detail">("detail");
  const itemGroupsRef = useRef<ItemGroup[]>([]);
  const sourceRef = useRef<"master" | "detail">("detail");

  // groupedData에서 선택된 행 추출 (마스터든 디테일이든 그대로)
  const selectedRows = useMemo(() => {
    if (!groupedData) return [];
    if (Array.isArray(groupedData)) return groupedData;
    if (groupedData.selectedRows) return groupedData.selectedRows;
    if (groupedData.data) return groupedData.data;
    return [];
  }, [groupedData]);

  // 선택된 행의 ID 목록 추출 (문자열)
  const selectedIds = useMemo(() => {
    return selectedRows
      .map((row: any) => String(row.id))
      .filter((id: string) => id && id !== "undefined" && id !== "null");
  }, [selectedRows]);

  const loadData = useCallback(async () => {
    if (selectedIds.length === 0 || isDesignMode) return;

    setLoading(true);
    try {
      // ID만 보내면 백엔드에서 소스 감지 + JOIN + 정규화
      const res = await getShippingPlanAggregate(selectedIds);

      if (!res.success) {
        toast.error("집계 데이터 조회 실패");
        return;
      }

      setSource(res.source);
      const aggregateData = res.data || {};

      const groups: ItemGroup[] = Object.entries(aggregateData).map(
        ([partCode, data]) => {
          const details: PlanDetailRow[] = [];

          // 수주별로 기존 계획 합산량 계산
          const existingPlansBySource = new Map<string, number>();
          for (const plan of data.existingPlans || []) {
            const prev = existingPlansBySource.get(plan.sourceId) || 0;
            existingPlansBySource.set(plan.sourceId, prev + plan.planQty);
          }

          // 신규 행 먼저: 모든 수주에 대해 항상 추가 (분할출하 대응)
          for (const order of data.orders || []) {
            const alreadyPlanned = existingPlansBySource.get(order.sourceId) || 0;
            const remainingBalance = Math.max(0, order.balanceQty - alreadyPlanned);
            details.push({
              type: "new",
              sourceId: order.sourceId,
              orderNo: order.orderNo,
              partnerName: order.partnerName,
              dueDate: order.dueDate,
              balanceQty: remainingBalance,
              planQty: 0,
              planDate: new Date().toISOString().split("T")[0],
              splitKey: `${order.sourceId}_0`,
            });
          }

          // 기존 출하계획 아래에 표시
          for (const plan of data.existingPlans || []) {
            const matchOrder = data.orders?.find(
              (o) => o.sourceId === plan.sourceId
            );
            details.push({
              type: "existing",
              sourceId: plan.sourceId,
              orderNo: matchOrder?.orderNo || "-",
              partnerName: matchOrder?.partnerName || "-",
              dueDate: matchOrder?.dueDate || "-",
              balanceQty: matchOrder?.balanceQty || 0,
              planQty: plan.planQty,
              existingPlanId: plan.id,
            });
          }

          // partName: orders에서 가져오기
          const partName =
            data.orders?.[0]?.partName || partCode;

          return {
            partCode,
            partName,
            aggregation: {
              totalBalance: data.totalBalance,
              totalPlanQty: data.totalPlanQty,
              currentStock: data.currentStock,
              availableStock: data.availableStock,
              inProductionQty: data.inProductionQty,
            },
            details,
          };
        }
      );

      setItemGroups(groups);
    } catch (err) {
      console.error("[v2-shipping-plan-editor] 데이터 로드 실패:", err);
      toast.error("데이터를 불러오는데 실패했습니다");
    } finally {
      setLoading(false);
    }
  }, [selectedIds, isDesignMode]);

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

  // ref 동기화 (이벤트 핸들러에서 최신 state 접근용)
  useEffect(() => {
    itemGroupsRef.current = itemGroups;
  }, [itemGroups]);

  useEffect(() => {
    sourceRef.current = source;
  }, [source]);

  // 저장 로직 (ref 기반으로 최신 state 접근, 재구독 방지)
  const savingRef = useRef(false);
  const onCloseRef = useRef(onClose);
  onCloseRef.current = onClose;

  const configRef = useRef(config);
  configRef.current = config;

  const handleSave = useCallback(async () => {
    if (savingRef.current) return;

    const currentGroups = itemGroupsRef.current;
    const currentSource = sourceRef.current;
    const currentConfig = configRef.current;

    const plans = currentGroups.flatMap((g) =>
      g.details
        .filter((d) => d.type === "new" && d.planQty > 0)
        .map((d) => ({
          sourceId: d.sourceId,
          planQty: d.planQty,
          planDate: d.planDate || new Date().toISOString().split("T")[0],
          balanceQty: d.balanceQty,
        }))
    );

    if (plans.length === 0) {
      toast.warning("저장할 출하계획이 없습니다. 수량을 입력해주세요.");
      return;
    }

    // 같은 sourceId별 합산 → 미출하량 초과 검증
    if (!currentConfig.allowOverPlan) {
      const sumBySource = new Map<string, { total: number; balance: number }>();
      for (const p of plans) {
        const prev = sumBySource.get(p.sourceId) || { total: 0, balance: p.balanceQty };
        sumBySource.set(p.sourceId, {
          total: prev.total + p.planQty,
          balance: prev.balance,
        });
      }
      for (const [, val] of sumBySource) {
        if (val.balance > 0 && val.total > val.balance) {
          toast.error("분할 출하계획의 합산이 미출하량을 초과합니다.");
          return;
        }
      }
    }

    // 저장 전 확인 (confirmBeforeSave = true일 때)
    if (currentConfig.confirmBeforeSave) {
      const msg = currentConfig.confirmMessage || "출하계획을 저장하시겠습니까?";
      if (!window.confirm(msg)) return;
    }

    savingRef.current = true;
    setSaving(true);
    try {
      const savePlans = plans.map((p) => ({ sourceId: p.sourceId, planQty: p.planQty, planDate: p.planDate }));
      const res = await batchSaveShippingPlans(savePlans, currentSource);
      if (res.success) {
        toast.success(`${plans.length}건의 출하계획이 저장되었습니다.`);
        if (currentConfig.autoCloseOnSave !== false && onCloseRef.current) {
          onCloseRef.current();
        }
      } else {
        toast.error(res.error || "출하계획 저장에 실패했습니다.");
      }
    } catch (err) {
      console.error("[v2-shipping-plan-editor] 저장 실패:", err);
      toast.error("출하계획 저장 중 오류가 발생했습니다.");
    } finally {
      savingRef.current = false;
      setSaving(false);
    }
  }, []);

  // V2 이벤트 버스 구독 (마운트 1회만, ref로 최신 핸들러 참조)
  const handleSaveRef = useRef(handleSave);
  handleSaveRef.current = handleSave;

  useEffect(() => {
    let unsubscribe: (() => void) | null = null;
    let mounted = true;

    (async () => {
      const { v2EventBus, V2_EVENTS } = await import("@/lib/v2-core");
      if (!mounted) return;
      unsubscribe = v2EventBus.subscribe(V2_EVENTS.SHIPPING_PLAN_SAVE, () => {
        handleSaveRef.current();
      });
    })();

    return () => {
      mounted = false;
      if (unsubscribe) unsubscribe();
    };
  }, []);

  // 집계 재계산 헬퍼
  const recalcAggregation = (group: ItemGroup): ItemGroup => {
    const newPlanTotal = group.details
      .filter((d) => d.type === "new")
      .reduce((sum, d) => sum + d.planQty, 0);
    const existingPlanTotal = group.details
      .filter((d) => d.type === "existing")
      .reduce((sum, d) => sum + d.planQty, 0);
    return {
      ...group,
      aggregation: {
        ...group.aggregation,
        totalPlanQty: existingPlanTotal + newPlanTotal,
        availableStock:
          group.aggregation.currentStock - (existingPlanTotal + newPlanTotal),
      },
    };
  };

  const handlePlanQtyChange = useCallback(
    (groupIdx: number, detailIdx: number, value: string) => {
      setItemGroups((prev) => {
        const next = [...prev];
        const group = { ...next[groupIdx] };
        const details = [...group.details];
        const target = details[detailIdx];
        let qty = Number(value) || 0;

        // 같은 sourceId의 다른 신규 행 합산
        const otherSum = details
          .filter((d, i) => d.type === "new" && d.sourceId === target.sourceId && i !== detailIdx)
          .reduce((sum, d) => sum + d.planQty, 0);

        // 잔여 가능량 = 미출하량 - 다른 분할 행 합산
        const maxAllowed = Math.max(0, target.balanceQty - otherSum);
        qty = Math.min(qty, maxAllowed);
        qty = Math.max(0, qty);

        details[detailIdx] = { ...details[detailIdx], planQty: qty };
        group.details = details;
        next[groupIdx] = recalcAggregation(group);
        return next;
      });
    },
    []
  );

  // 출하계획일 변경
  const handlePlanDateChange = useCallback(
    (groupIdx: number, detailIdx: number, value: string) => {
      setItemGroups((prev) => {
        const next = [...prev];
        const group = { ...next[groupIdx] };
        const details = [...group.details];
        details[detailIdx] = { ...details[detailIdx], planDate: value };
        group.details = details;
        next[groupIdx] = group;
        return next;
      });
    },
    []
  );

  // 분할 행 추가 (같은 수주에 새 행)
  const handleAddSplitRow = useCallback(
    (groupIdx: number, sourceId: string) => {
      setItemGroups((prev) => {
        const next = [...prev];
        const group = { ...next[groupIdx] };
        const details = [...group.details];

        // 같은 sourceId의 신규 행 중 마지막 찾기
        const existingNewRows = details.filter(
          (d) => d.type === "new" && d.sourceId === sourceId
        );
        const baseRow = existingNewRows[0];
        if (!baseRow) return prev;

        const splitCount = existingNewRows.length;
        const newRow: PlanDetailRow = {
          type: "new",
          sourceId,
          orderNo: baseRow.orderNo,
          partnerName: baseRow.partnerName,
          dueDate: baseRow.dueDate,
          balanceQty: baseRow.balanceQty,
          planQty: 0,
          planDate: new Date().toISOString().split("T")[0],
          splitKey: `${sourceId}_${splitCount}`,
        };

        // 같은 sourceId 신규 행 바로 뒤에 삽입
        const lastNewIdx = details.reduce(
          (last, d, i) =>
            d.type === "new" && d.sourceId === sourceId ? i : last,
          -1
        );
        details.splice(lastNewIdx + 1, 0, newRow);

        group.details = details;
        next[groupIdx] = group;
        return next;
      });
    },
    []
  );

  // 분할 행 삭제
  const handleRemoveSplitRow = useCallback(
    (groupIdx: number, detailIdx: number) => {
      setItemGroups((prev) => {
        const next = [...prev];
        const group = { ...next[groupIdx] };
        const details = [...group.details];
        const target = details[detailIdx];

        // 같은 sourceId의 신규 행이 1개뿐이면 삭제 안 함 (최소 1행 유지)
        const sameSourceNewCount = details.filter(
          (d) => d.type === "new" && d.sourceId === target.sourceId
        ).length;
        if (sameSourceNewCount <= 1) {
          toast.warning("최소 1개의 출하계획 행이 필요합니다.");
          return prev;
        }

        details.splice(detailIdx, 1);
        group.details = details;
        next[groupIdx] = recalcAggregation(group);
        return next;
      });
    },
    []
  );

  if (isDesignMode) {
    return (
      <div className="flex h-full w-full flex-col gap-3 rounded-lg border border-dashed border-gray-300 p-4">
        <div className="flex items-center gap-2">
          <Truck className="h-5 w-5 text-muted-foreground" />
          <span className="text-sm font-medium text-muted-foreground">
            {config.title || "출하계획 등록"}
          </span>
        </div>
        <div className="flex gap-2">
          {[
            "총수주잔량",
            "총출하계획량",
            "현재고",
            "가용재고",
            "생산중수량",
          ].map((label) => (
            <div
              key={label}
              className="flex flex-1 flex-col items-center rounded-lg border border-gray-200 bg-gray-50 px-3 py-2"
            >
              <span className="text-lg font-bold text-gray-400">0</span>
              <span className="text-[10px] text-gray-400">{label}</span>
            </div>
          ))}
        </div>
        <div className="flex-1 rounded-lg border border-gray-200 bg-gray-50 p-3">
          <span className="text-xs text-gray-400">상세 테이블 영역</span>
        </div>
      </div>
    );
  }

  if (loading || saving) {
    return (
      <div className="flex h-full w-full items-center justify-center">
        <div className="flex flex-col items-center gap-3">
          <Loader2 className="h-8 w-8 animate-spin text-primary" />
          <span className="text-sm text-muted-foreground">
            {saving ? "출하계획 저장 중..." : "데이터 로딩 중..."}
          </span>
        </div>
      </div>
    );
  }

  if (selectedIds.length === 0) {
    return (
      <div className="flex h-full w-full items-center justify-center">
        <span className="text-sm text-muted-foreground">
          선택된 수주가 없습니다
        </span>
      </div>
    );
  }

  const showSummary = config.showSummaryCards !== false;
  const showExisting = config.showExistingPlans !== false;

  return (
    <div className="flex h-full w-full flex-col gap-4 overflow-auto p-4">
      {itemGroups.map((group, groupIdx) => (
        <div key={group.partCode} className="flex flex-col gap-3">
          <div className="flex items-center gap-2">
            <Package className="h-4 w-4 text-primary" />
            <span className="text-sm font-semibold">
              {group.partName} ({group.partCode})
            </span>
          </div>

          {showSummary && (
            <SummaryCards
              aggregation={group.aggregation}
              visibleCards={config.visibleSummaryCards}
            />
          )}

          <DetailTable
            details={group.details}
            groupIdx={groupIdx}
            onPlanQtyChange={handlePlanQtyChange}
            onPlanDateChange={handlePlanDateChange}
            onAddSplit={handleAddSplitRow}
            onRemoveSplit={handleRemoveSplitRow}
            showExisting={showExisting}
          />
        </div>
      ))}

    </div>
  );
};

interface VisibleCards {
  totalBalance?: boolean;
  totalPlanQty?: boolean;
  currentStock?: boolean;
  availableStock?: boolean;
  inProductionQty?: boolean;
}

const SummaryCards: React.FC<{
  aggregation: ItemAggregation;
  visibleCards?: VisibleCards;
}> = ({ aggregation, visibleCards }) => {
  const allCards = [
    {
      key: "totalBalance" as const,
      label: "총수주잔량",
      value: aggregation.totalBalance,
      icon: TrendingUp,
      color: {
        bg: "bg-blue-50",
        text: "text-blue-600",
        border: "border-blue-200",
      },
    },
    {
      key: "totalPlanQty" as const,
      label: "총출하계획량",
      value: aggregation.totalPlanQty,
      icon: Truck,
      color: {
        bg: "bg-indigo-50",
        text: "text-indigo-600",
        border: "border-indigo-200",
      },
    },
    {
      key: "currentStock" as const,
      label: "현재고",
      value: aggregation.currentStock,
      icon: Warehouse,
      color: {
        bg: "bg-emerald-50",
        text: "text-emerald-600",
        border: "border-emerald-200",
      },
    },
    {
      key: "availableStock" as const,
      label: "가용재고",
      value: aggregation.availableStock,
      icon: CheckCircle,
      color: {
        bg: aggregation.availableStock < 0 ? "bg-red-50" : "bg-amber-50",
        text:
          aggregation.availableStock < 0
            ? "text-red-600"
            : "text-amber-600",
        border:
          aggregation.availableStock < 0
            ? "border-red-200"
            : "border-amber-200",
      },
    },
    {
      key: "inProductionQty" as const,
      label: "생산중수량",
      value: aggregation.inProductionQty,
      icon: Factory,
      color: {
        bg: "bg-purple-50",
        text: "text-purple-600",
        border: "border-purple-200",
      },
    },
  ];

  const cards = allCards.filter(
    (c) => !visibleCards || visibleCards[c.key] !== false
  );

  return (
    <div className="flex gap-2">
      {cards.map((card) => {
        const Icon = card.icon;
        return (
          <div
            key={card.label}
            className={`flex flex-1 flex-col items-center rounded-lg border ${card.color.border} ${card.color.bg} px-3 py-2 transition-shadow hover:shadow-sm`}
          >
            <div className="flex items-center gap-1">
              <Icon className={`h-3.5 w-3.5 ${card.color.text}`} />
              <span className={`text-xl font-bold ${card.color.text}`}>
                {card.value.toLocaleString()}
              </span>
            </div>
            <span className={`mt-0.5 text-[10px] ${card.color.text}`}>
              {card.label}
            </span>
          </div>
        );
      })}
    </div>
  );
};

// sourceId별 그룹 (셀병합용)
interface SourceGroup {
  sourceId: string;
  orderNo: string;
  partnerName: string;
  dueDate: string;
  balanceQty: number;
  rows: (PlanDetailRow & { _origIdx: number })[];
}

const DetailTable: React.FC<{
  details: PlanDetailRow[];
  groupIdx: number;
  onPlanQtyChange: (groupIdx: number, detailIdx: number, value: string) => void;
  onPlanDateChange: (groupIdx: number, detailIdx: number, value: string) => void;
  onAddSplit: (groupIdx: number, sourceId: string) => void;
  onRemoveSplit: (groupIdx: number, detailIdx: number) => void;
  showExisting?: boolean;
}> = ({ details, groupIdx, onPlanQtyChange, onPlanDateChange, onAddSplit, onRemoveSplit, showExisting = true }) => {
  const visibleDetails = details
    .map((d, idx) => ({ ...d, _origIdx: idx }))
    .filter((d) => showExisting || d.type === "new");

  // sourceId별 그룹핑 (순서 유지)
  const sourceGroups = useMemo(() => {
    const map = new Map<string, SourceGroup>();
    const order: string[] = [];
    for (const d of visibleDetails) {
      if (!map.has(d.sourceId)) {
        map.set(d.sourceId, {
          sourceId: d.sourceId,
          orderNo: d.orderNo,
          partnerName: d.partnerName,
          dueDate: d.dueDate,
          balanceQty: d.balanceQty,
          rows: [],
        });
        order.push(d.sourceId);
      }
      map.get(d.sourceId)!.rows.push(d);
    }
    return order.map((id) => map.get(id)!);
  }, [visibleDetails]);

  // 같은 sourceId 신규 행들의 planQty 합산 (잔여량 계산용)
  const getRemaining = (sourceId: string, excludeOrigIdx: number) => {
    const group = sourceGroups.find((g) => g.sourceId === sourceId);
    if (!group) return 0;
    const otherSum = group.rows
      .filter((r) => r.type === "new" && r._origIdx !== excludeOrigIdx)
      .reduce((sum, r) => sum + r.planQty, 0);
    return Math.max(0, group.balanceQty - otherSum);
  };

  return (
    <div className="overflow-hidden rounded-lg border">
      <table className="w-full text-sm">
        <thead>
          <tr className="border-b bg-muted/50">
            <th className="w-14 px-3 py-2 text-left text-xs font-medium text-muted-foreground">
              구분
            </th>
            <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
              수주번호
            </th>
            <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
              거래처
            </th>
            <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
              납기일
            </th>
            <th className="px-3 py-2 text-right text-xs font-medium text-muted-foreground">
              미출하
            </th>
            <th className="px-3 py-2 text-center text-xs font-medium text-muted-foreground">
              출하계획량
            </th>
            <th className="px-3 py-2 text-center text-xs font-medium text-muted-foreground">
              출하계획일
            </th>
            <th className="w-16 px-2 py-2 text-center text-xs font-medium text-muted-foreground">
              분할
            </th>
          </tr>
        </thead>
        <tbody>
          {sourceGroups.map((sg) => {
            const totalRows = sg.rows.length;
            const newCount = sg.rows.filter((r) => r.type === "new").length;
            return sg.rows.map((row, rowIdx) => {
              const isFirst = rowIdx === 0;
              const remaining = row.type === "new" ? getRemaining(row.sourceId, row._origIdx) : 0;
              const isDisabled = row.type === "new" && sg.balanceQty <= 0;

              return (
                <tr
                  key={row.splitKey || `${row.type}-${row.sourceId}-${row.existingPlanId || row._origIdx}`}
                  className={`hover:bg-muted/30 ${rowIdx < totalRows - 1 ? "" : "border-b"}`}
                >
                  {/* 구분 - 매 행마다 표시 */}
                  <td className={`px-3 py-2 ${!isFirst ? "border-t border-dashed border-muted" : "border-t"}`}>
                    {row.type === "existing" ? (
                      <Badge variant="secondary" className="text-[10px]">기존</Badge>
                    ) : (
                      <Badge className="bg-primary text-[10px] text-primary-foreground">신규</Badge>
                    )}
                  </td>

                  {/* 수주번호, 거래처, 납기일, 미출하 - 첫 행만 rowSpan */}
                  {isFirst && (
                    <>
                      <td className="border-t px-3 py-2 text-xs align-middle" rowSpan={totalRows}>
                        {sg.orderNo}
                      </td>
                      <td className="border-t px-3 py-2 text-xs align-middle" rowSpan={totalRows}>
                        {sg.partnerName}
                      </td>
                      <td className="border-t px-3 py-2 text-xs align-middle" rowSpan={totalRows}>
                        {sg.dueDate || "-"}
                      </td>
                      <td className="border-t px-3 py-2 text-right text-xs font-bold align-middle" rowSpan={totalRows}>
                        {sg.balanceQty.toLocaleString()}
                      </td>
                    </>
                  )}

                  {/* 출하계획량 */}
                  <td className={`px-3 py-2 text-center ${!isFirst ? "border-t border-dashed border-muted" : "border-t"}`}>
                    {row.type === "existing" ? (
                      <span className="text-xs text-muted-foreground">
                        {row.planQty.toLocaleString()}
                      </span>
                    ) : (
                      <Input
                        type="number"
                        min={0}
                        max={remaining}
                        value={row.planQty || ""}
                        onChange={(e) => onPlanQtyChange(groupIdx, row._origIdx, e.target.value)}
                        disabled={isDisabled}
                        className="mx-auto h-7 w-24 text-center text-xs disabled:opacity-40"
                        placeholder="0"
                      />
                    )}
                  </td>

                  {/* 출하계획일 */}
                  <td className={`px-3 py-2 text-center ${!isFirst ? "border-t border-dashed border-muted" : "border-t"}`}>
                    {row.type === "existing" ? (
                      <span className="text-xs text-muted-foreground">-</span>
                    ) : (
                      <Input
                        type="date"
                        value={row.planDate || ""}
                        onChange={(e) => onPlanDateChange(groupIdx, row._origIdx, e.target.value)}
                        disabled={isDisabled}
                        className="mx-auto h-7 w-32 text-xs disabled:opacity-40"
                      />
                    )}
                  </td>

                  {/* 분할 버튼 */}
                  <td className={`px-2 py-2 text-center ${!isFirst ? "border-t border-dashed border-muted" : "border-t"}`}>
                    {row.type === "new" && isFirst && (
                      <button
                        type="button"
                        onClick={() => onAddSplit(groupIdx, row.sourceId)}
                        disabled={sg.balanceQty <= 0}
                        className="flex h-6 w-6 items-center justify-center rounded-md text-primary hover:bg-primary/10 disabled:opacity-30 disabled:cursor-not-allowed mx-auto"
                        title="분할 행 추가"
                      >
                        <Plus className="h-3.5 w-3.5" />
                      </button>
                    )}
                    {row.type === "new" && !isFirst && newCount > 1 && (
                      <button
                        type="button"
                        onClick={() => onRemoveSplit(groupIdx, row._origIdx)}
                        className="flex h-6 w-6 items-center justify-center rounded-md text-destructive hover:bg-destructive/10 mx-auto"
                        title="분할 행 삭제"
                      >
                        <X className="h-3.5 w-3.5" />
                      </button>
                    )}
                  </td>
                </tr>
              );
            });
          })}
          {sourceGroups.length === 0 && (
            <tr>
              <td colSpan={8} className="px-3 py-6 text-center text-xs text-muted-foreground">
                데이터가 없습니다
              </td>
            </tr>
          )}
        </tbody>
      </table>
    </div>
  );
};

export const ShippingPlanEditorWrapper: React.FC<
  ShippingPlanEditorComponentProps
> = (props) => {
  return <ShippingPlanEditorComponent {...props} />;
};
