"use client";

import React, { useState, useMemo, 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 { Badge } from "@/components/ui/badge";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
  DialogDescription,
} from "@/components/ui/dialog";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Download,
  Plus,
  Save,
  ClipboardList,
  Inbox,
  Check,
  ChevronsUpDown,
  Loader2,
  FileSpreadsheet,
  Trash2,
  Pencil,
  FileText,
  Wrench,
  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 { useConfirmDialog } from "@/components/common/ConfirmDialog";
import { useTableSettings } from "@/hooks/useTableSettings";
import { TableSettingsModal } from "@/components/common/TableSettingsModal";
import { DynamicSearchFilter, FilterValue } from "@/components/common/DynamicSearchFilter";
import { ExcelUploadModal } from "@/components/common/ExcelUploadModal";
import { exportToExcel } from "@/lib/utils/excelExport";

// --- 상수 ---
const TABLE_NAME = "claim_mng";

const GRID_COLUMNS = [
  { key: "claim_no", label: "클레임번호" },
  { key: "claim_date", label: "접수일자" },
  { key: "claim_type", label: "유형" },
  { key: "claim_status", label: "상태" },
  { key: "customer_name", label: "거래처명" },
  { key: "manager_name", label: "담당자" },
  { key: "claim_content", label: "클레임 내용" },
];

type ClaimType = "불량" | "교환" | "반품" | "배송지연" | "기타";
type ClaimStatus = "접수" | "처리중" | "완료" | "취소";

interface ClaimRow {
  id: number;
  claim_no: string;
  claim_date: string;
  claim_type: string;
  claim_status: string;
  customer_code: string;
  customer_name: string;
  manager_name: string;
  order_no: string;
  claim_content: string;
  process_content: string;
  company_code?: string;
  writer?: string;
  created_date?: string;
  updated_date?: string;
  [key: string]: any;
}

interface CustomerOption {
  customerCode: string;
  customerName: string;
}

interface SalesOrderOption {
  orderNo: string;
  partnerName: string;
  status: string;
}

// Badge variant 매핑 (CSS 변수 기반)
const getClaimStatusVariant = (status: string) => {
  switch (status) {
    case "접수": return "default" as const;
    case "처리중": return "secondary" as const;
    case "완료": return "outline" as const;
    case "취소": return "destructive" as const;
    default: return "secondary" as const;
  }
};

const getClaimTypeVariant = (type: string) => {
  switch (type) {
    case "불량": return "destructive" as const;
    case "교환": return "warning" as const;
    case "반품": return "default" as const;
    case "배송지연": return "secondary" as const;
    case "기타": return "outline" as const;
    default: return "outline" as const;
  }
};

const CLAIM_TYPES: ClaimType[] = ["불량", "교환", "반품", "배송지연", "기타"];
const CLAIM_STATUSES: ClaimStatus[] = ["접수", "처리중", "완료", "취소"];

export default function ClaimManagementPage() {
  useAuth();
  const { confirm, ConfirmDialogComponent } = useConfirmDialog();
  const ts = useTableSettings("c16-claim", TABLE_NAME, GRID_COLUMNS);

  const [data, setData] = useState<ClaimRow[]>([]);
  const [loading, setLoading] = useState(false);
  const [totalCount, setTotalCount] = useState(0);
  const [selectedClaimNo, setSelectedClaimNo] = useState<string | null>(null);

  // 검색 필터 (DynamicSearchFilter에서 관리)
  const [searchFilters, setSearchFilters] = useState<FilterValue[]>([]);

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

  // 모달 상태
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isEditMode, setIsEditMode] = useState(false);
  const [saving, setSaving] = useState(false);
  const [formData, setFormData] = useState<Partial<ClaimRow>>({});

  // Combobox 상태
  const [customerOpen, setCustomerOpen] = useState(false);
  const [orderOpen, setOrderOpen] = useState(false);

  // DB 데이터
  const [customers, setCustomers] = useState<CustomerOption[]>([]);
  const [salesOrders, setSalesOrders] = useState<SalesOrderOption[]>([]);
  const [customersLoading, setCustomersLoading] = useState(false);
  const [ordersLoading, setOrdersLoading] = useState(false);

  // --- 데이터 조회 (서버사이드 필터 + autoFilter 멀티테넌시) ---
  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const filters = searchFilters.map(f => ({
        columnName: f.columnName,
        operator: f.operator,
        value: f.value,
      }));

      const res = await apiClient.post(`/table-management/tables/${TABLE_NAME}/data`, {
        page: 1,
        size: 500,
        dataFilter: filters.length > 0 ? { enabled: true, filters } : undefined,
        autoFilter: true,
        sort: { columnName: "claim_date", order: "desc" },
      });

      const rows: ClaimRow[] = res.data?.data?.data || res.data?.data?.rows || [];
      setData(rows);
      setTotalCount(res.data?.data?.total || rows.length);
    } catch {
      toast.error("클레임 목록을 불러오는데 실패했습니다.");
    } finally {
      setLoading(false);
    }
  }, [searchFilters]);

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


  // 거래처 목록 조회 (autoFilter로 멀티테넌시 적용)
  const fetchCustomers = useCallback(async (force = false) => {
    if (!force && customers.length > 0) return;
    setCustomersLoading(true);
    try {
      const res = await apiClient.post("/table-management/tables/customer_mng/data", {
        page: 1,
        size: 9999,
        autoFilter: true,
      });
      const rows = res.data?.data?.data || res.data?.data?.rows;
      if (res.data?.success && Array.isArray(rows)) {
        const list: CustomerOption[] = rows.map((row: any) => ({
          customerCode: row.customer_code || row.id || "",
          customerName: row.customer_name || "",
        }));
        setCustomers(list);
      }
    } catch {
      /* skip */
    } finally {
      setCustomersLoading(false);
    }
  }, [customers.length]);

  // 수주 목록 조회 (autoFilter로 멀티테넌시 적용)
  const fetchSalesOrders = useCallback(async (force = false) => {
    if (!force && salesOrders.length > 0) return;
    setOrdersLoading(true);
    try {
      const res = await apiClient.post("/table-management/tables/sales_order_mng/data", {
        page: 1,
        size: 9999,
        autoFilter: true,
      });
      const rows = res.data?.data?.data || res.data?.data?.rows;
      if (res.data?.success && Array.isArray(rows)) {
        const seen = new Set<string>();
        const list: SalesOrderOption[] = [];
        for (const row of rows) {
          const orderNo = row.order_no || "";
          if (!orderNo || seen.has(orderNo)) continue;
          seen.add(orderNo);
          list.push({
            orderNo,
            partnerName: row.partner_id || "",
            status: row.status || "",
          });
        }
        setSalesOrders(list);
      }
    } catch {
      /* skip */
    } finally {
      setOrdersLoading(false);
    }
  }, [salesOrders.length]);

  // 상태별 카운트
  const statusCounts = useMemo(() => {
    const counts = { 접수: 0, 처리중: 0, 완료: 0, 취소: 0 };
    data.forEach((claim) => {
      if (counts[claim.claim_status as keyof typeof counts] !== undefined) {
        counts[claim.claim_status as keyof typeof counts]++;
      }
    });
    return counts;
  }, [data]);

  // 클레임번호 자동 생성
  const generateClaimNo = useCallback(() => {
    const year = new Date().getFullYear();
    const prefix = `CLM-${year}-`;
    const existingNumbers = data
      .filter((c) => c.claim_no?.startsWith(prefix))
      .map((c) => parseInt(c.claim_no.replace(prefix, ""), 10))
      .filter((n) => !isNaN(n));
    const maxNumber = existingNumbers.length > 0 ? Math.max(...existingNumbers) : 0;
    return `${prefix}${String(maxNumber + 1).padStart(3, "0")}`;
  }, [data]);

  const handleRowClick = (claimNo: string) => {
    setSelectedClaimNo(claimNo);
  };

  const openRegisterModal = () => {
    setIsEditMode(false);
    setFormData({
      claim_no: generateClaimNo(),
      claim_date: new Date().toISOString().split("T")[0],
      claim_type: undefined,
      claim_status: "접수",
      customer_code: "",
      customer_name: "",
      manager_name: "",
      order_no: "",
      claim_content: "",
      process_content: "",
    });
    setIsModalOpen(true);
    fetchCustomers(true);
    fetchSalesOrders(true);
  };

  const openEditModal = (claimNo: string) => {
    const claim = data.find((c) => c.claim_no === claimNo);
    if (!claim) return;
    setIsEditMode(true);
    setFormData({ ...claim });
    setIsModalOpen(true);
    fetchCustomers(true);
    fetchSalesOrders(true);
  };

  const handleFormChange = (field: string, value: string) => {
    setFormData((prev) => ({ ...prev, [field]: value }));
  };

  // --- 저장 (table-management API, company_code 자동 주입) ---
  const handleSave = async () => {
    if (!formData.claim_type || !formData.customer_name || !formData.claim_content) {
      toast.error("필수 항목을 모두 입력해주세요. (클레임유형, 거래처명, 클레임내용)");
      return;
    }

    setSaving(true);
    try {
      const { id, company_code, writer, created_date, updated_date, created_by, updated_by, ...saveFields } = formData as any;

      if (isEditMode && id) {
        await apiClient.put(`/table-management/tables/${TABLE_NAME}/edit`, {
          originalData: { id },
          updatedData: saveFields,
        });
        toast.success("클레임이 수정되었어요.");
      } else {
        await apiClient.post(`/table-management/tables/${TABLE_NAME}/add`, saveFields);
        toast.success("클레임이 등록되었어요.");
      }

      setIsModalOpen(false);
      fetchData();
    } catch (err: any) {
      console.error("클레임 저장 실패:", err);
      toast.error(err.response?.data?.message || "저장에 실패했어요.");
    } finally {
      setSaving(false);
    }
  };

  // --- 삭제 ---
  const handleDelete = async (claimNo: string) => {
    const claim = data.find((c) => c.claim_no === claimNo);
    if (!claim) return;

    const ok = await confirm(`클레임 ${claimNo}을(를) 삭제하시겠습니까?`, {
      variant: "destructive",
      confirmText: "삭제",
    });
    if (!ok) return;

    try {
      await apiClient.delete(`/table-management/tables/${TABLE_NAME}/delete`, {
        data: [{ id: claim.id }],
      });
      toast.success("클레임이 삭제되었어요.");
      if (selectedClaimNo === claimNo) setSelectedClaimNo(null);
      fetchData();
    } catch (err: any) {
      console.error("클레임 삭제 실패:", err);
      toast.error(err.response?.data?.message || "삭제에 실패했어요.");
    }
  };

  // 엑셀 다운로드
  const handleExcelDownload = async () => {
    if (data.length === 0) {
      toast.error("다운로드할 데이터가 없어요.");
      return;
    }
    try {
      const exportData = data.map((row) => ({
        클레임번호: row.claim_no,
        접수일자: row.claim_date,
        클레임유형: row.claim_type,
        처리상태: row.claim_status,
        거래처코드: row.customer_code,
        거래처명: row.customer_name,
        담당자: row.manager_name,
        수주번호: row.order_no,
        클레임내용: row.claim_content,
        처리내용: row.process_content,
      }));
      await exportToExcel(exportData, "클레임관리.xlsx", "클레임");
      toast.success("엑셀 다운로드 완료");
    } catch (err) {
      console.error("엑셀 다운로드 실패:", err);
      toast.error("엑셀 다운로드에 실패했어요.");
    }
  };

  const selectedClaim = useMemo(
    () => data.find((c) => c.claim_no === selectedClaimNo),
    [data, selectedClaimNo]
  );

  return (
    <div className="flex flex-col h-[calc(100vh-4rem)] overflow-hidden">
      {/* 검색 필터 (DynamicSearchFilter) */}
      <DynamicSearchFilter
        tableName={TABLE_NAME}
        filterId="c16-claim"
        onFilterChange={setSearchFilters}
        dataCount={data.length}
        externalFilterConfig={ts.filterConfig}
      />

      {/* ───── 메인 분할 레이아웃 ───── */}
      <div className="flex-1 overflow-hidden">
        <ResizablePanelGroup direction="horizontal" className="h-full">
          {/* ── 좌측: 클레임 목록 (65%) ── */}
          <ResizablePanel defaultSize={65} minSize={35}>
            <div className="flex flex-col h-full bg-card">
              {/* 패널 헤더 */}
              <div className="flex items-center justify-between px-4 py-2.5 border-b bg-muted/40 shrink-0">
                <div className="flex items-center gap-2">
                  <ClipboardList className="w-4 h-4 text-muted-foreground" />
                  <span className="text-[13px] font-bold text-foreground">클레임 목록</span>
                  <span className="text-[11px] font-semibold text-primary bg-primary/8 border border-primary/15 px-2 py-0.5 rounded-full font-mono">
                    {data.length}건
                  </span>
                  {loading && <Loader2 className="w-3.5 h-3.5 animate-spin text-muted-foreground" />}
                </div>
                <div className="flex items-center gap-1.5">
                  <Button variant="outline" size="sm" onClick={() => setExcelUploadOpen(true)}>
                    <FileSpreadsheet className="w-3.5 h-3.5" />
                    업로드
                  </Button>
                  <Button variant="outline" size="sm" onClick={handleExcelDownload}>
                    <Download className="w-3.5 h-3.5" />
                    다운로드
                  </Button>
                  <Button size="sm" onClick={openRegisterModal}>
                    <Plus className="w-3.5 h-3.5" />
                    등록
                  </Button>
                  <Button variant="ghost" size="sm" onClick={() => ts.setOpen(true)} title="테이블 설정">
                    <Settings2 className="h-4 w-4" />
                  </Button>
                </div>
              </div>

              {/* 테이블 */}
              <div className="flex-1 overflow-auto">
                <Table>
                  <TableHeader className="sticky top-0 z-10">
                    <TableRow className="bg-muted hover:bg-muted">
                      <TableHead className="w-[40px] text-center text-[11px] font-bold uppercase tracking-wide">#</TableHead>
                      {ts.visibleColumns.map((col) => (
                        <TableHead key={col.key} className="text-[11px] font-bold uppercase tracking-wide">
                          {col.label}
                        </TableHead>
                      ))}
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {loading && data.length === 0 ? (
                      <TableRow>
                        <TableCell colSpan={ts.visibleColumns.length + 1} className="h-32 text-center">
                          <div className="flex items-center justify-center gap-2 text-muted-foreground">
                            <Loader2 className="w-4 h-4 animate-spin" />
                            <span className="text-sm">불러오는 중...</span>
                          </div>
                        </TableCell>
                      </TableRow>
                    ) : data.length === 0 ? (
                      <TableRow>
                        <TableCell colSpan={ts.visibleColumns.length + 1} className="h-32 text-center">
                          <div className="flex flex-col items-center gap-2 text-muted-foreground">
                            <Inbox className="w-8 h-8 opacity-30" />
                            <span className="text-sm">등록된 클레임이 없어요</span>
                          </div>
                        </TableCell>
                      </TableRow>
                    ) : (
                      data.map((claim, idx) => (
                        <TableRow
                          key={claim.id}
                          className={cn(
                            "cursor-pointer transition-colors",
                            selectedClaimNo === claim.claim_no
                              ? "bg-primary/8 border-l-2 border-l-primary"
                              : "hover:bg-muted/50"
                          )}
                          onClick={() => handleRowClick(claim.claim_no)}
                          onDoubleClick={() => openEditModal(claim.claim_no)}
                        >
                          <TableCell className="text-center text-[11px] text-muted-foreground py-2">
                            {idx + 1}
                          </TableCell>
                          {ts.visibleColumns.map((col) => {
                            if (col.key === "claim_type") {
                              return (
                                <TableCell key={col.key} className="text-center py-2">
                                  <Badge variant={getClaimTypeVariant(claim.claim_type)} className="text-[10px] px-1.5 py-0">
                                    {claim.claim_type}
                                  </Badge>
                                </TableCell>
                              );
                            }
                            if (col.key === "claim_status") {
                              return (
                                <TableCell key={col.key} className="text-center py-2">
                                  <Badge variant={getClaimStatusVariant(claim.claim_status)} className="text-[10px] px-1.5 py-0">
                                    {claim.claim_status}
                                  </Badge>
                                </TableCell>
                              );
                            }
                            if (col.key === "claim_content") {
                              return (
                                <TableCell key={col.key} className="text-sm text-muted-foreground py-2 max-w-[200px] truncate">
                                  {claim.claim_content}
                                </TableCell>
                              );
                            }
                            return (
                              <TableCell key={col.key} className="text-sm py-2">
                                {claim[col.key] ?? "-"}
                              </TableCell>
                            );
                          })}
                        </TableRow>
                      ))
                    )}
                  </TableBody>
                </Table>
              </div>
            </div>
          </ResizablePanel>

          <ResizableHandle withHandle />

          {/* ── 우측: 클레임 상세 (35%) ── */}
          <ResizablePanel defaultSize={35} minSize={20}>
            <div className="flex flex-col h-full bg-card border-l">
              {/* 패널 헤더 */}
              <div className="flex items-center justify-between px-4 py-2.5 border-b bg-muted/40 shrink-0">
                <div className="flex items-center gap-2">
                  <ClipboardList className="w-4 h-4 text-muted-foreground" />
                  <span className="text-[13px] font-bold text-foreground">클레임 상세</span>
                  {selectedClaim && (
                    <span className="text-[11px] font-mono text-muted-foreground">{selectedClaim.claim_no}</span>
                  )}
                </div>
                {selectedClaim && (
                  <div className="flex items-center gap-1.5">
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => openEditModal(selectedClaim.claim_no)}
                    >
                      <Pencil className="w-3.5 h-3.5" />
                      수정
                    </Button>
                    <Button
                      variant="outline"
                      size="sm"
                      className="text-destructive hover:text-destructive"
                      onClick={() => handleDelete(selectedClaim.claim_no)}
                    >
                      <Trash2 className="w-3.5 h-3.5" />
                    </Button>
                  </div>
                )}
              </div>

              {/* 상태별 요약 카운트 */}
              <div className="flex items-center gap-3 px-4 py-2 border-b bg-muted/20 shrink-0">
                {([
                  { label: "접수", count: statusCounts["접수"], variant: "default" as const },
                  { label: "처리중", count: statusCounts["처리중"], variant: "secondary" as const },
                  { label: "완료", count: statusCounts["완료"], variant: "outline" as const },
                  { label: "취소", count: statusCounts["취소"], variant: "destructive" as const },
                ]).map((item) => (
                  <div key={item.label} className="flex items-center gap-1">
                    <Badge variant={item.variant} className="text-[10px] px-1.5 py-0">
                      {item.label}
                    </Badge>
                    <span className="text-sm font-bold tabular-nums text-foreground">{item.count}</span>
                  </div>
                ))}
              </div>

              {/* 상세 컨텐츠 */}
              <div className="flex-1 overflow-auto">
                {selectedClaim ? (
                  <div className="p-4 space-y-4">
                    {/* 기본 정보 그리드 */}
                    <div className="grid grid-cols-2 gap-x-4 gap-y-3">
                      <div>
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground mb-1">접수일자</p>
                        <p className="text-sm text-foreground">{selectedClaim.claim_date}</p>
                      </div>
                      <div>
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground mb-1">담당자</p>
                        <p className="text-sm text-foreground">{selectedClaim.manager_name || "-"}</p>
                      </div>
                      <div>
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground mb-1">유형</p>
                        <Badge variant={getClaimTypeVariant(selectedClaim.claim_type)} className="text-[11px]">
                          {selectedClaim.claim_type}
                        </Badge>
                      </div>
                      <div>
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground mb-1">상태</p>
                        <Badge variant={getClaimStatusVariant(selectedClaim.claim_status)} className="text-[11px]">
                          {selectedClaim.claim_status}
                        </Badge>
                      </div>
                      <div>
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground mb-1">거래처명</p>
                        <p className="text-sm font-medium text-foreground">{selectedClaim.customer_name}</p>
                      </div>
                      <div>
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground mb-1">수주번호</p>
                        <p className="text-sm font-mono text-muted-foreground">{selectedClaim.order_no || "-"}</p>
                      </div>
                    </div>

                    <div className="border-t" />

                    {/* 클레임 내용 */}
                    <div>
                      <div className="flex items-center gap-1.5 mb-1.5">
                        <FileText className="w-3.5 h-3.5 text-muted-foreground" />
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">클레임 내용</p>
                      </div>
                      <div className="rounded-md border bg-muted/30 p-3 text-sm text-foreground whitespace-pre-wrap min-h-[60px]">
                        {selectedClaim.claim_content || "-"}
                      </div>
                    </div>

                    {/* 처리 내용 */}
                    <div>
                      <div className="flex items-center gap-1.5 mb-1.5">
                        <Wrench className="w-3.5 h-3.5 text-muted-foreground" />
                        <p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">처리 내용</p>
                      </div>
                      <div className="rounded-md border bg-muted/30 p-3 text-sm text-foreground whitespace-pre-wrap min-h-[60px]">
                        {selectedClaim.process_content || "-"}
                      </div>
                    </div>
                  </div>
                ) : (
                  <div className="flex flex-col items-center justify-center h-full text-center p-8">
                    <div className="rounded-full border-2 border-dashed border-muted-foreground/20 w-14 h-14 flex items-center justify-center mb-4">
                      <Inbox className="w-7 h-7 text-muted-foreground/30" />
                    </div>
                    <p className="text-sm font-medium text-muted-foreground mb-1">
                      좌측에서 클레임을 선택해주세요
                    </p>
                    <p className="text-xs text-muted-foreground/60">
                      클레임을 선택하면 상세 정보가 표시돼요
                    </p>
                  </div>
                )}
              </div>
            </div>
          </ResizablePanel>
        </ResizablePanelGroup>
      </div>

      {/* ───── 클레임 등록/수정 모달 ───── */}
      <Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
        <DialogContent className="max-w-[900px] max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{isEditMode ? "클레임 수정" : "클레임 등록"}</DialogTitle>
            <DialogDescription>
              {isEditMode ? "클레임 정보를 수정해요." : "새로운 클레임을 등록해요."}
            </DialogDescription>
          </DialogHeader>

          <div className="flex flex-col md:flex-row gap-4 py-2">
            {/* 왼쪽: 기본 정보 */}
            <div className="md:w-[320px] shrink-0 space-y-3 bg-muted/30 p-4 rounded-lg border">
              <h3 className="text-[13px] font-bold pb-2 border-b text-foreground">기본 정보</h3>

              <div className="space-y-1">
                <Label htmlFor="claim_no" className="text-[11px] font-semibold text-muted-foreground">클레임번호</Label>
                <Input
                  id="claim_no"
                  value={formData.claim_no || ""}
                  readOnly
                  className="h-9 text-sm bg-muted cursor-not-allowed font-mono"
                />
              </div>

              <div className="space-y-1">
                <Label htmlFor="claim_date" className="text-[11px] font-semibold text-muted-foreground">접수일자</Label>
                <Input
                  id="claim_date"
                  type="date"
                  value={formData.claim_date || ""}
                  onChange={(e) => handleFormChange("claim_date", e.target.value)}
                  className="h-9 text-sm"
                />
              </div>

              <div className="space-y-1">
                <Label htmlFor="claim_type" className="text-[11px] font-semibold text-muted-foreground">
                  클레임 유형 <span className="text-destructive">*</span>
                </Label>
                <Select
                  value={formData.claim_type || ""}
                  onValueChange={(v) => handleFormChange("claim_type", v)}
                >
                  <SelectTrigger className="h-9">
                    <SelectValue placeholder="유형을 선택해주세요" />
                  </SelectTrigger>
                  <SelectContent>
                    {CLAIM_TYPES.map((t) => (
                      <SelectItem key={t} value={t}>{t}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>

              <div className="space-y-1">
                <Label htmlFor="claim_status" className="text-[11px] font-semibold text-muted-foreground">처리 상태</Label>
                <Select
                  value={formData.claim_status || "접수"}
                  onValueChange={(v) => handleFormChange("claim_status", v)}
                >
                  <SelectTrigger className="h-9">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {CLAIM_STATUSES.map((s) => (
                      <SelectItem key={s} value={s}>{s}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>

              <div className="space-y-1">
                <Label className="text-[11px] font-semibold text-muted-foreground">
                  거래처명 <span className="text-destructive">*</span>
                </Label>
                <Popover open={customerOpen} onOpenChange={setCustomerOpen}>
                  <PopoverTrigger asChild>
                    <Button
                      variant="outline"
                      role="combobox"
                      aria-expanded={customerOpen}
                      className="h-9 w-full justify-between font-normal"
                      onClick={() => fetchCustomers(false)}
                    >
                      {formData.customer_name || "거래처를 선택해주세요"}
                      <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent
                    className="p-0"
                    style={{ width: "var(--radix-popover-trigger-width)" }}
                    align="start"
                  >
                    <Command>
                      <CommandInput placeholder="거래처 검색..." />
                      <CommandList>
                        {customersLoading ? (
                          <div className="flex items-center justify-center py-6">
                            <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                            <span className="ml-2 text-xs text-muted-foreground">로딩 중...</span>
                          </div>
                        ) : (
                          <>
                            <CommandEmpty className="py-4 text-center text-sm">
                              거래처를 찾을 수 없어요.
                            </CommandEmpty>
                            <CommandGroup>
                              {customers.map((cust) => (
                                <CommandItem
                                  key={cust.customerCode}
                                  value={`${cust.customerCode} ${cust.customerName}`}
                                  onSelect={() => {
                                    setFormData((prev) => ({
                                      ...prev,
                                      customer_code: cust.customerCode,
                                      customer_name: cust.customerName,
                                    }));
                                    setCustomerOpen(false);
                                  }}
                                >
                                  <Check
                                    className={cn(
                                      "mr-2 h-4 w-4",
                                      formData.customer_code === cust.customerCode
                                        ? "opacity-100"
                                        : "opacity-0"
                                    )}
                                  />
                                  <div className="flex flex-col min-w-0">
                                    <span className="font-medium truncate">{cust.customerName}</span>
                                    <span className="text-[10px] text-muted-foreground">{cust.customerCode}</span>
                                  </div>
                                </CommandItem>
                              ))}
                            </CommandGroup>
                          </>
                        )}
                      </CommandList>
                    </Command>
                  </PopoverContent>
                </Popover>
              </div>

              <div className="space-y-1">
                <Label htmlFor="manager_name" className="text-[11px] font-semibold text-muted-foreground">담당자</Label>
                <Input
                  id="manager_name"
                  value={formData.manager_name || ""}
                  onChange={(e) => handleFormChange("manager_name", e.target.value)}
                  placeholder="담당자를 입력해주세요"
                  className="h-9"
                />
              </div>

              <div className="space-y-1">
                <Label className="text-[11px] font-semibold text-muted-foreground">수주번호</Label>
                <Popover open={orderOpen} onOpenChange={setOrderOpen}>
                  <PopoverTrigger asChild>
                    <Button
                      variant="outline"
                      role="combobox"
                      aria-expanded={orderOpen}
                      className="h-9 w-full justify-between font-normal"
                      onClick={() => fetchSalesOrders(false)}
                    >
                      {formData.order_no || "수주번호를 선택해주세요"}
                      <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent
                    className="p-0"
                    style={{ width: "var(--radix-popover-trigger-width)" }}
                    align="start"
                  >
                    <Command>
                      <CommandInput placeholder="수주번호 검색..." />
                      <CommandList>
                        {ordersLoading ? (
                          <div className="flex items-center justify-center py-6">
                            <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                            <span className="ml-2 text-xs text-muted-foreground">로딩 중...</span>
                          </div>
                        ) : (
                          <>
                            <CommandEmpty className="py-4 text-center text-sm">
                              수주번호를 찾을 수 없어요.
                            </CommandEmpty>
                            <CommandGroup>
                              {salesOrders.map((order) => (
                                <CommandItem
                                  key={order.orderNo}
                                  value={`${order.orderNo} ${order.partnerName}`}
                                  onSelect={() => {
                                    setFormData((prev) => ({
                                      ...prev,
                                      order_no: order.orderNo,
                                    }));
                                    setOrderOpen(false);
                                  }}
                                >
                                  <Check
                                    className={cn(
                                      "mr-2 h-4 w-4",
                                      formData.order_no === order.orderNo
                                        ? "opacity-100"
                                        : "opacity-0"
                                    )}
                                  />
                                  <div className="flex flex-col min-w-0">
                                    <span className="font-medium truncate">{order.orderNo}</span>
                                    <span className="text-[10px] text-muted-foreground">
                                      {order.status}
                                      {order.partnerName ? ` | ${order.partnerName}` : ""}
                                    </span>
                                  </div>
                                </CommandItem>
                              ))}
                            </CommandGroup>
                          </>
                        )}
                      </CommandList>
                    </Command>
                  </PopoverContent>
                </Popover>
              </div>
            </div>

            {/* 오른쪽: 상세 내용 */}
            <div className="flex-1 space-y-3 bg-muted/30 p-4 rounded-lg border min-w-0">
              <h3 className="text-[13px] font-bold pb-2 border-b text-foreground">클레임 상세 내용</h3>

              <div className="space-y-1">
                <Label htmlFor="claim_content" className="text-[11px] font-semibold text-muted-foreground">
                  클레임 내용 <span className="text-destructive">*</span>
                </Label>
                <Textarea
                  id="claim_content"
                  value={formData.claim_content || ""}
                  onChange={(e) => handleFormChange("claim_content", e.target.value)}
                  placeholder="클레임 내용을 상세히 입력해주세요"
                  className="min-h-[200px] resize-y text-sm"
                />
              </div>

              <div className="space-y-1">
                <Label htmlFor="process_content" className="text-[11px] font-semibold text-muted-foreground">처리 내용</Label>
                <Textarea
                  id="process_content"
                  value={formData.process_content || ""}
                  onChange={(e) => handleFormChange("process_content", e.target.value)}
                  placeholder="처리 내용을 입력해주세요"
                  className="min-h-[150px] resize-y text-sm"
                />
              </div>
            </div>
          </div>

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

      {/* 엑셀 업로드 모달 */}
      <ExcelUploadModal
        open={excelUploadOpen}
        onOpenChange={setExcelUploadOpen}
        tableName={TABLE_NAME}
        onSuccess={() => {
          fetchData();
          toast.success("엑셀 업로드가 완료되었어요.");
        }}
      />

      {/* 확인 다이얼로그 */}
      {ConfirmDialogComponent}

      <TableSettingsModal
        open={ts.open}
        onOpenChange={ts.setOpen}
        tableName={ts.tableName}
        settingsId={ts.settingsId}
        defaultVisibleKeys={ts.defaultVisibleKeys}
        onSave={ts.applySettings}
      />
    </div>
  );
}
