"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { GitBranch, Loader2, PackagePlus, Pencil, Plus, Save, Search, Star, Trash2 } from "lucide-react";
import { toast } from "sonner";

import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import {
  createRoutingVersion,
  getProcessList,
  getRegisteredItems,
  getRoutingDetails,
  getRoutingVersions,
  registerItemsBatch,
  saveRoutingDetails,
  searchAllItems,
  unregisterItem,
  type ItemForRouting,
  type ProcessMaster,
  type RegisteredItem,
  type RoutingDetail,
  type RoutingVersion,
} from "@/lib/api/processInfo";
import { cn } from "@/lib/utils";

function normalizeDefaultFlag(v: RoutingVersion): boolean {
  const raw = v.is_default as unknown;
  if (typeof raw === "boolean") return raw;
  if (raw === "t" || raw === true || raw === "Y" || raw === "true") return true;
  return false;
}

function sortDetailsBySeq(rows: RoutingDetail[]): RoutingDetail[] {
  return [...rows].sort((a, b) => {
    const na = parseInt(String(a.seq_no), 10) || 0;
    const nb = parseInt(String(b.seq_no), 10) || 0;
    return na - nb;
  });
}

export function ItemRoutingTab() {
  const [searchInput, setSearchInput] = useState("");
  const [debouncedSearch, setDebouncedSearch] = useState("");
  const [items, setItems] = useState<RegisteredItem[]>([]);
  const [itemsLoading, setItemsLoading] = useState(false);
  const [selectedItem, setSelectedItem] = useState<RegisteredItem | null>(null);

  const [versions, setVersions] = useState<RoutingVersion[]>([]);
  const [versionsLoading, setVersionsLoading] = useState(false);
  const [selectedVersionId, setSelectedVersionId] = useState<string | null>(null);

  const [details, setDetails] = useState<RoutingDetail[]>([]);
  const [detailsLoading, setDetailsLoading] = useState(false);
  const [saving, setSaving] = useState(false);

  const [selectedDetailIds, setSelectedDetailIds] = useState<Set<string>>(new Set());

  const [processes, setProcesses] = useState<ProcessMaster[]>([]);
  const [processesLoading, setProcessesLoading] = useState(false);

  const [versionDialogOpen, setVersionDialogOpen] = useState(false);
  const [versionName, setVersionName] = useState("");
  const [versionDescription, setVersionDescription] = useState("");
  const [versionIsDefault, setVersionIsDefault] = useState(false);
  const [versionSubmitting, setVersionSubmitting] = useState(false);

  const [detailDialogOpen, setDetailDialogOpen] = useState(false);
  const [detailDialogMode, setDetailDialogMode] = useState<"add" | "edit">("add");
  const [editingDetailId, setEditingDetailId] = useState<string | null>(null);
  const [formProcessCode, setFormProcessCode] = useState("");
  const [formSeqNo, setFormSeqNo] = useState("");
  const [formRequired, setFormRequired] = useState("Y");
  const [formFixedOrder, setFormFixedOrder] = useState("Y");
  const [formWorkType, setFormWorkType] = useState("내부");
  const [formStandardTime, setFormStandardTime] = useState("");
  const [formOutsource, setFormOutsource] = useState("");
  const [detailSubmitting, setDetailSubmitting] = useState(false);

  // 품목 등록 모달 state
  const [registerDialogOpen, setRegisterDialogOpen] = useState(false);
  const [registerSearch, setRegisterSearch] = useState("");
  const [registerSearchDebounced, setRegisterSearchDebounced] = useState("");
  const [registerItems, setRegisterItems] = useState<ItemForRouting[]>([]);
  const [registerLoading, setRegisterLoading] = useState(false);
  const [registerSelectedIds, setRegisterSelectedIds] = useState<Set<string>>(new Set());
  const [registerSubmitting, setRegisterSubmitting] = useState(false);

  useEffect(() => {
    const t = window.setTimeout(() => setDebouncedSearch(searchInput.trim()), 300);
    return () => window.clearTimeout(t);
  }, [searchInput]);

  useEffect(() => {
    const t = window.setTimeout(() => setRegisterSearchDebounced(registerSearch.trim()), 300);
    return () => window.clearTimeout(t);
  }, [registerSearch]);

  const loadItems = useCallback(async (search: string) => {
    setItemsLoading(true);
    try {
      const res = await getRegisteredItems(search || undefined);
      if (res.success && res.data) {
        setItems(res.data);
      } else {
        toast.error(res.message || "품목 목록을 불러오지 못했습니다.");
        setItems([]);
      }
    } finally {
      setItemsLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadItems(debouncedSearch);
  }, [debouncedSearch, loadItems]);

  const loadProcesses = useCallback(async () => {
    setProcessesLoading(true);
    try {
      const procRes = await getProcessList({ useYn: "Y" });
      if (!procRes.success || !procRes.data) {
        toast.error(procRes.message || "공정 목록을 불러오지 못했습니다.");
        setProcesses([]);
        return;
      }
      setProcesses(procRes.data);
    } finally {
      setProcessesLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadProcesses();
  }, [loadProcesses]);

  // 등록 모달 품목 검색
  const loadRegisterItems = useCallback(async (search: string) => {
    setRegisterLoading(true);
    try {
      const res = await searchAllItems(search || undefined);
      if (res.success && res.data) {
        setRegisterItems(res.data);
      } else {
        setRegisterItems([]);
      }
    } finally {
      setRegisterLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!registerDialogOpen) return;
    void loadRegisterItems(registerSearchDebounced);
  }, [registerSearchDebounced, registerDialogOpen, loadRegisterItems]);

  // 이미 등록된 품목인지 판별 (item_code 기준)
  const registeredItemCodes = useMemo(() => new Set(items.map((i) => i.item_code)), [items]);

  const handleRegisterItems = async () => {
    if (registerSelectedIds.size === 0) {
      toast.error("등록할 품목을 선택하세요.");
      return;
    }
    setRegisterSubmitting(true);
    try {
      const selected = registerItems.filter((ri) => registerSelectedIds.has(ri.id));
      const batchItems = selected.map((item) => ({
        itemId: item.id,
        itemCode: item.item_number,
      }));
      const res = await registerItemsBatch(batchItems);
      if (res.success) {
        toast.success(`${batchItems.length}건 품목이 등록되었습니다.`);
        setRegisterDialogOpen(false);
        setRegisterSearch("");
        setRegisterSelectedIds(new Set());
        void loadItems(debouncedSearch);
      } else {
        toast.error(res.message || "품목 등록에 실패했습니다.");
      }
    } finally {
      setRegisterSubmitting(false);
    }
  };

  const loadVersions = useCallback(async (item: RegisteredItem, preferVersionId?: string) => {
    setVersionsLoading(true);
    setVersions([]);
    setSelectedVersionId(null);
    setDetails([]);
    setSelectedDetailIds(new Set());
    try {
      const res = await getRoutingVersions(item.item_code);
      if (!res.success || !res.data) {
        toast.error(res.message || "라우팅 버전을 불러오지 못했습니다.");
        return;
      }
      const list = res.data.map((v) => ({ ...v, is_default: normalizeDefaultFlag(v) }));
      setVersions(list);
      const preferred = preferVersionId ? list.find((v) => v.id === preferVersionId) : undefined;
      const def = list.find((v) => v.is_default);
      const pick = preferred ?? def ?? list[0];
      if (pick) setSelectedVersionId(pick.id);
    } finally {
      setVersionsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!selectedItem) return;
    void loadVersions(selectedItem);
  }, [selectedItem, loadVersions]);

  const loadDetails = useCallback(async (versionId: string) => {
    setDetailsLoading(true);
    setSelectedDetailIds(new Set());
    try {
      const res = await getRoutingDetails(versionId);
      if (res.success && res.data) {
        setDetails(sortDetailsBySeq(res.data));
      } else {
        toast.error(res.message || "라우팅 공정을 불러오지 못했습니다.");
        setDetails([]);
      }
    } finally {
      setDetailsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!selectedVersionId) {
      setDetails([]);
      return;
    }
    void loadDetails(selectedVersionId);
  }, [selectedVersionId, loadDetails]);

  const showOutsourceField = formWorkType === "외주" || formWorkType === "선택가능";

  const openAddDetailDialog = () => {
    if (!selectedVersionId) {
      toast.error("먼저 라우팅 버전을 선택하세요.");
      return;
    }
    setDetailDialogMode("add");
    setEditingDetailId(null);
    setFormProcessCode("");
    const nextSeq = details.length === 0 ? 1 : Math.max(...details.map((d) => parseInt(String(d.seq_no), 10) || 0)) + 1;
    setFormSeqNo(String(nextSeq));
    setFormRequired("Y");
    setFormFixedOrder("Y");
    setFormWorkType("내부");
    setFormStandardTime("");
    setFormOutsource("");
    setDetailDialogOpen(true);
  };

  const openEditDetailDialog = () => {
    if (!selectedVersionId) {
      toast.error("먼저 라우팅 버전을 선택하세요.");
      return;
    }
    if (selectedDetailIds.size !== 1) {
      toast.error("수정할 공정 한 건만 선택하세요.");
      return;
    }
    const id = [...selectedDetailIds][0];
    const row = details.find((d) => d.id === id);
    if (!row) {
      toast.error("선택한 공정을 찾을 수 없습니다.");
      return;
    }
    setDetailDialogMode("edit");
    setEditingDetailId(row.id);
    setFormProcessCode(row.process_code);
    setFormSeqNo(String(row.seq_no));
    setFormRequired(row.is_required === "N" ? "N" : "Y");
    setFormFixedOrder(row.is_fixed_order === "N" ? "N" : "Y");
    setFormWorkType(row.work_type || "내부");
    setFormStandardTime(row.standard_time || "");
    setFormOutsource(row.outsource_supplier || "");
    setDetailDialogOpen(true);
  };

  const submitDetailForm = () => {
    if (!selectedVersionId) return;
    if (!formProcessCode) {
      toast.error("공정을 선택하세요.");
      return;
    }
    const seq = parseInt(formSeqNo, 10);
    if (Number.isNaN(seq) || seq < 1) {
      toast.error("올바른 순번을 입력하세요.");
      return;
    }
    const st = formStandardTime.trim();
    if (st !== "" && Number.isNaN(Number(st))) {
      toast.error("표준작업시간은 숫자로 입력하세요.");
      return;
    }
    const proc = processes.find((p) => p.process_code === formProcessCode);
    const outsource = showOutsourceField ? formOutsource.trim() : "";

    setDetailSubmitting(true);
    try {
      if (detailDialogMode === "add") {
        const newRow: RoutingDetail = {
          id: `new-${crypto.randomUUID()}`,
          routing_version_id: selectedVersionId,
          seq_no: String(seq),
          process_code: formProcessCode,
          process_name: proc?.process_name,
          is_required: formRequired,
          is_fixed_order: formFixedOrder,
          work_type: formWorkType,
          standard_time: st || "0",
          outsource_supplier: outsource,
        };
        setDetails((prev) => sortDetailsBySeq([...prev, newRow]));
        toast.success("공정이 추가되었습니다. 저장을 눌러 반영하세요.");
      } else if (editingDetailId) {
        setDetails((prev) =>
          sortDetailsBySeq(
            prev.map((d) =>
              d.id === editingDetailId
                ? {
                    ...d,
                    seq_no: String(seq),
                    process_code: formProcessCode,
                    process_name: proc?.process_name ?? d.process_name,
                    is_required: formRequired,
                    is_fixed_order: formFixedOrder,
                    work_type: formWorkType,
                    standard_time: st || "0",
                    outsource_supplier: outsource,
                  }
                : d,
            ),
          ),
        );
        toast.success("공정이 수정되었습니다. 저장을 눌러 반영하세요.");
      }
      setDetailDialogOpen(false);
    } finally {
      setDetailSubmitting(false);
    }
  };

  const deleteSelectedDetails = () => {
    if (selectedDetailIds.size === 0) {
      toast.error("삭제할 공정을 선택하세요.");
      return;
    }
    setDetails((prev) => prev.filter((d) => !selectedDetailIds.has(d.id)));
    setSelectedDetailIds(new Set());
    toast.success("선택한 공정이 목록에서 제거되었습니다. 저장을 눌러 반영하세요.");
  };

  const toggleDetailSelected = (id: string, checked: boolean) => {
    setSelectedDetailIds((prev) => {
      const next = new Set(prev);
      if (checked) next.add(id);
      else next.delete(id);
      return next;
    });
  };

  const toggleAllDetails = (checked: boolean) => {
    if (!checked) {
      setSelectedDetailIds(new Set());
      return;
    }
    setSelectedDetailIds(new Set(details.map((d) => d.id)));
  };

  const allDetailsSelected = details.length > 0 && details.every((d) => selectedDetailIds.has(d.id));

  const persistDetails = async () => {
    if (!selectedVersionId) {
      toast.error("저장할 버전이 없습니다.");
      return;
    }
    const payload = details.map((d) => ({
      seq_no: String(d.seq_no),
      process_code: d.process_code,
      is_required: d.is_required || "Y",
      is_fixed_order: d.is_fixed_order || "Y",
      work_type: d.work_type || "내부",
      standard_time: String(d.standard_time ?? "0"),
      outsource_supplier: d.outsource_supplier || "",
    }));

    setSaving(true);
    try {
      const res = await saveRoutingDetails(selectedVersionId, payload);
      if (res.success) {
        toast.success("저장되었습니다.");
        await loadDetails(selectedVersionId);
      } else {
        toast.error(res.message || "저장에 실패했습니다.");
      }
    } finally {
      setSaving(false);
    }
  };

  const submitNewVersion = async () => {
    if (!selectedItem) return;
    const name = versionName.trim();
    if (!name) {
      toast.error("버전명을 입력하세요.");
      return;
    }
    setVersionSubmitting(true);
    try {
      const res = await createRoutingVersion({
        item_code: selectedItem.item_code,
        version_name: name,
        description: versionDescription.trim() || undefined,
        is_default: versionIsDefault || undefined,
      });
      if (res.success && res.data) {
        toast.success("버전이 추가되었습니다.");
        setVersionDialogOpen(false);
        setVersionName("");
        setVersionDescription("");
        setVersionIsDefault(false);
        const created = res.data as RoutingVersion;
        await loadVersions(selectedItem, created?.id);
      } else {
        toast.error(res.message || "버전 추가에 실패했습니다.");
      }
    } finally {
      setVersionSubmitting(false);
    }
  };

  return (
    <div className="flex min-h-[420px] w-full flex-1 flex-col md:min-h-[560px]">
      <ResizablePanelGroup
        direction="horizontal"
        className="border-border flex min-h-[420px] flex-1 rounded-lg border md:min-h-[560px]"
      >
        <ResizablePanel defaultSize={30} minSize={18} className="min-w-0">
          <div className="flex h-full flex-col gap-3 p-3 sm:p-4">
            <div className="flex items-center gap-2">
              <div className="relative flex-1">
                <Search className="text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 h-3.5 w-3.5 -translate-y-1/2 sm:h-4 sm:w-4" />
              <Input
                value={searchInput}
                onChange={(e) => setSearchInput(e.target.value)}
                placeholder="품목코드 / 품목명 검색"
                className="focus-visible:ring-ring h-8 pl-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:pl-9 sm:text-sm"
                aria-label="품목 검색"
              />
              </div>
              <Button
                type="button"
                size="icon"
                variant="outline"
                className="h-8 w-8 shrink-0 sm:h-10 sm:w-10"
                onClick={() => {
                  setRegisterSearch("");
                  setRegisterSelectedIds(new Set());
                  setRegisterItems([]);
                  setRegisterDialogOpen(true);
                }}
                title="품목 등록"
              >
                <PackagePlus className="h-4 w-4" />
              </Button>
            </div>
            <div className="min-h-0 flex-1 overflow-hidden">
              {itemsLoading ? (
                <div className="text-muted-foreground flex h-40 items-center justify-center gap-2 text-xs sm:text-sm">
                  <Loader2 className="text-primary h-5 w-5 animate-spin" />
                  불러오는 중...
                </div>
              ) : items.length === 0 ? (
                <div className="flex flex-col items-center justify-center gap-3 px-1 py-10">
                  <p className="text-muted-foreground text-center text-xs sm:text-sm">등록된 품목이 없습니다.</p>
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="gap-1 text-xs"
                    onClick={() => {
                      setRegisterSearch("");
                      setRegisterSelectedIds(new Set());
                      setRegisterItems([]);
                      setRegisterDialogOpen(true);
                    }}
                  >
                    <PackagePlus className="h-3.5 w-3.5" />
                    품목 등록하기
                  </Button>
                </div>
              ) : (
                <div className="flex h-full max-h-[calc(100vh-16rem)] flex-col gap-2 overflow-y-auto pr-1">
                  {items.map((item) => {
                    const active = selectedItem?.id === item.id;
                    return (
                      <button
                        key={item.id}
                        type="button"
                        onClick={() => setSelectedItem(item)}
                        className={cn(
                          "focus-visible:ring-ring w-full rounded-lg border p-3 text-left transition-colors focus-visible:ring-2 focus-visible:ring-offset-2",
                          "border-border bg-card hover:bg-accent/50 shadow-sm",
                          active && "border-primary ring-ring/30 ring-2",
                        )}
                      >
                        <p className="text-foreground text-xs font-medium sm:text-sm">{item.item_code}</p>
                        <p className="text-muted-foreground mt-0.5 line-clamp-2 text-[11px] sm:text-xs">
                          {item.item_name}
                        </p>
                      </button>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </ResizablePanel>

        <ResizableHandle withHandle />

        <ResizablePanel defaultSize={70} minSize={35} className="min-w-0">
          <div className="flex h-full min-h-0 flex-col">
            {!selectedItem ? (
              <div className="text-muted-foreground flex flex-1 flex-col items-center justify-center gap-2 px-4 text-center text-xs sm:text-sm">
                <GitBranch className="h-8 w-8 opacity-50" aria-hidden />
                좌측에서 품목을 선택하면 라우팅을 관리할 수 있습니다.
              </div>
            ) : (
              <>
                <div className="border-border flex shrink-0 flex-col gap-3 border-b p-3 sm:p-4">
                  <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                    <div className="min-w-0">
                      <p className="text-foreground text-xs font-semibold sm:text-sm">{selectedItem.item_name}</p>
                      <p className="text-muted-foreground mt-0.5 text-[11px] sm:text-xs">
                        품목코드 {selectedItem.item_code}
                      </p>
                    </div>
                    <div className="flex shrink-0 gap-2">
                      <Button
                        type="button"
                        size="sm"
                        variant="destructive"
                        className="h-8 gap-1 text-xs sm:h-9 sm:text-sm"
                        onClick={async () => {
                          if (!selectedItem.registered_id) return;
                          const res = await unregisterItem(selectedItem.registered_id);
                          if (res.success) {
                            toast.success("품목 등록이 해제되었습니다.");
                            setSelectedItem(null);
                            void loadItems(debouncedSearch);
                          } else {
                            toast.error(res.message || "등록 해제에 실패했습니다.");
                          }
                        }}
                      >
                        <Trash2 className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
                        등록 해제
                      </Button>
                      <Button
                        type="button"
                        size="sm"
                        className="h-8 gap-1 text-xs sm:h-9 sm:text-sm"
                        onClick={() => {
                          setVersionName("");
                          setVersionDescription("");
                          setVersionIsDefault(false);
                          setVersionDialogOpen(true);
                        }}
                      >
                        <Plus className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
                        버전 추가
                      </Button>
                    </div>
                  </div>

                  <div className="flex flex-wrap items-center gap-2">
                    {versionsLoading ? (
                      <div className="text-muted-foreground flex items-center gap-2 text-xs sm:text-sm">
                        <Loader2 className="text-primary h-4 w-4 animate-spin" />
                        버전 불러오는 중...
                      </div>
                    ) : versions.length === 0 ? (
                      <p className="text-muted-foreground text-xs sm:text-sm">
                        등록된 버전이 없습니다. 버전을 추가하세요.
                      </p>
                    ) : (
                      versions.map((v) => {
                        const selected = v.id === selectedVersionId;
                        const def = normalizeDefaultFlag(v);
                        return (
                          <button
                            key={v.id}
                            type="button"
                            onClick={() => setSelectedVersionId(v.id)}
                            className={cn(
                              "focus-visible:ring-ring inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 sm:text-sm",
                              selected
                                ? "border-primary bg-primary text-primary-foreground"
                                : "border-border bg-secondary text-secondary-foreground hover:bg-secondary/80",
                            )}
                          >
                            {def && (
                              <Star
                                className={cn(
                                  "h-3.5 w-3.5 sm:h-4 sm:w-4",
                                  selected ? "fill-primary-foreground" : "fill-warning text-warning",
                                )}
                                aria-label="기본 버전"
                              />
                            )}
                            {v.version_name}
                          </button>
                        );
                      })
                    )}
                  </div>
                </div>

                <div className="flex min-h-0 flex-1 flex-col gap-3 p-3 sm:p-4">
                  <div className="flex flex-wrap gap-2">
                    <Button
                      type="button"
                      variant="secondary"
                      size="sm"
                      className="h-8 text-xs sm:h-9 sm:text-sm"
                      onClick={openAddDetailDialog}
                      disabled={!selectedVersionId || detailsLoading}
                    >
                      <Plus className="mr-1 h-3.5 w-3.5" />
                      공정 추가
                    </Button>
                    <Button
                      type="button"
                      variant="secondary"
                      size="sm"
                      className="h-8 text-xs sm:h-9 sm:text-sm"
                      onClick={openEditDetailDialog}
                      disabled={!selectedVersionId || detailsLoading}
                    >
                      <Pencil className="mr-1 h-3.5 w-3.5" />
                      수정
                    </Button>
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      className="h-8 text-xs sm:h-9 sm:text-sm"
                      onClick={deleteSelectedDetails}
                      disabled={!selectedVersionId || detailsLoading}
                    >
                      <Trash2 className="mr-1 h-3.5 w-3.5" />
                      선택 삭제
                    </Button>
                    <Button
                      type="button"
                      size="sm"
                      className="h-8 text-xs sm:h-9 sm:text-sm"
                      onClick={() => void persistDetails()}
                      disabled={!selectedVersionId || detailsLoading || saving}
                    >
                      {saving ? (
                        <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
                      ) : (
                        <Save className="mr-1 h-3.5 w-3.5" />
                      )}
                      저장
                    </Button>
                  </div>

                  <div className="border-border min-h-0 flex-1 overflow-hidden rounded-md border">
                    {detailsLoading ? (
                      <div className="text-muted-foreground flex h-48 items-center justify-center gap-2 text-xs sm:text-sm">
                        <Loader2 className="text-primary h-5 w-5 animate-spin" />
                        공정 순서 불러오는 중...
                      </div>
                    ) : !selectedVersionId ? (
                      <p className="text-muted-foreground p-6 text-center text-xs sm:text-sm">버전을 선택하세요.</p>
                    ) : (
                      <div className="h-full max-h-[calc(100vh-20rem)] overflow-auto">
                        <Table>
                          <TableHeader>
                            <TableRow className="hover:bg-transparent">
                              <TableHead className="w-10">
                                <Checkbox
                                  checked={allDetailsSelected}
                                  onCheckedChange={(c) => toggleAllDetails(c === true)}
                                  aria-label="전체 선택"
                                  className="focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-2"
                                />
                              </TableHead>
                              <TableHead className="text-xs sm:text-sm">순번</TableHead>
                              <TableHead className="text-xs sm:text-sm">공정명</TableHead>
                              <TableHead className="text-xs sm:text-sm">필수</TableHead>
                              <TableHead className="text-xs sm:text-sm">순서고정</TableHead>
                              <TableHead className="text-xs sm:text-sm">작업구분</TableHead>
                              <TableHead className="text-xs sm:text-sm">표준시간</TableHead>
                              <TableHead className="text-xs sm:text-sm">외주업체</TableHead>
                            </TableRow>
                          </TableHeader>
                          <TableBody>
                            {details.length === 0 ? (
                              <TableRow>
                                <TableCell
                                  colSpan={8}
                                  className="text-muted-foreground py-10 text-center text-xs sm:text-sm"
                                >
                                  등록된 공정이 없습니다.
                                </TableCell>
                              </TableRow>
                            ) : (
                              details.map((row) => (
                                <TableRow key={row.id}>
                                  <TableCell>
                                    <Checkbox
                                      checked={selectedDetailIds.has(row.id)}
                                      onCheckedChange={(c) => toggleDetailSelected(row.id, c === true)}
                                      aria-label={`${row.process_name || row.process_code} 선택`}
                                      className="focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-2"
                                    />
                                  </TableCell>
                                  <TableCell className="text-xs sm:text-sm">{row.seq_no}</TableCell>
                                  <TableCell className="text-xs sm:text-sm">
                                    {row.process_name || row.process_code}
                                  </TableCell>
                                  <TableCell className="text-xs sm:text-sm">
                                    {row.is_required === "N" ? "N" : "Y"}
                                  </TableCell>
                                  <TableCell className="text-xs sm:text-sm">
                                    {row.is_fixed_order === "N" ? "N" : "Y"}
                                  </TableCell>
                                  <TableCell className="text-xs sm:text-sm">{row.work_type}</TableCell>
                                  <TableCell className="text-xs sm:text-sm">{row.standard_time}</TableCell>
                                  <TableCell className="max-w-[140px] truncate text-xs sm:text-sm">
                                    {row.outsource_supplier || "—"}
                                  </TableCell>
                                </TableRow>
                              ))
                            )}
                          </TableBody>
                        </Table>
                      </div>
                    )}
                  </div>
                </div>
              </>
            )}
          </div>
        </ResizablePanel>
      </ResizablePanelGroup>

      <Dialog open={versionDialogOpen} onOpenChange={setVersionDialogOpen}>
        <DialogContent className="max-w-[95vw] sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle className="text-base sm:text-lg">라우팅 버전 추가</DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">
              선택한 품목에 새 라우팅 버전을 추가합니다.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3 sm:space-y-4">
            <div>
              <Label htmlFor="versionName" className="text-xs sm:text-sm">
                버전명 <span className="text-destructive">*</span>
              </Label>
              <Input
                id="versionName"
                value={versionName}
                onChange={(e) => setVersionName(e.target.value)}
                placeholder="예: Rev.A"
                className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm"
              />
            </div>
            <div>
              <Label htmlFor="versionDesc" className="text-xs sm:text-sm">
                설명
              </Label>
              <Input
                id="versionDesc"
                value={versionDescription}
                onChange={(e) => setVersionDescription(e.target.value)}
                placeholder="선택 입력"
                className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm"
              />
            </div>
            <div className="flex items-center gap-2">
              <Checkbox
                id="versionDefault"
                checked={versionIsDefault}
                onCheckedChange={(c) => setVersionIsDefault(c === true)}
                className="focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-2"
              />
              <Label htmlFor="versionDefault" className="text-xs font-normal sm:text-sm">
                기본 버전으로 설정
              </Label>
            </div>
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              onClick={() => setVersionDialogOpen(false)}
              className="focus-visible:ring-ring h-8 flex-1 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:flex-none sm:text-sm"
            >
              취소
            </Button>
            <Button
              type="button"
              onClick={() => void submitNewVersion()}
              disabled={versionSubmitting}
              className="focus-visible:ring-ring h-8 flex-1 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:flex-none sm:text-sm"
            >
              {versionSubmitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
              추가
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={detailDialogOpen} onOpenChange={setDetailDialogOpen}>
        <DialogContent className="max-w-[95vw] sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle className="text-base sm:text-lg">
              {detailDialogMode === "add" ? "공정 추가" : "공정 수정"}
            </DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">
              라우팅 공정 순서에 반영할 내용을 입력합니다. 적용 후 저장을 눌러주세요.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3 sm:space-y-4">
            <div>
              <Label className="text-xs sm:text-sm">
                공정 <span className="text-destructive">*</span>
              </Label>
              <Select value={formProcessCode} onValueChange={setFormProcessCode}>
                <SelectTrigger
                  className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm"
                  aria-label="공정 선택"
                >
                  <SelectValue placeholder={processesLoading ? "불러오는 중..." : "공정 선택"} />
                </SelectTrigger>
                <SelectContent>
                  {processes.map((p) => (
                    <SelectItem key={p.id} value={p.process_code} className="text-xs sm:text-sm">
                      {p.process_name} ({p.process_code})
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label htmlFor="seqNo" className="text-xs sm:text-sm">
                순번 <span className="text-destructive">*</span>
              </Label>
              <Input
                id="seqNo"
                type="number"
                min={1}
                value={formSeqNo}
                onChange={(e) => setFormSeqNo(e.target.value)}
                className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm"
              />
            </div>
            <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
              <div>
                <Label className="text-xs sm:text-sm">필수여부</Label>
                <Select value={formRequired} onValueChange={setFormRequired}>
                  <SelectTrigger className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="Y" className="text-xs sm:text-sm">
                      Y
                    </SelectItem>
                    <SelectItem value="N" className="text-xs sm:text-sm">
                      N
                    </SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div>
                <Label className="text-xs sm:text-sm">순서고정여부</Label>
                <Select value={formFixedOrder} onValueChange={setFormFixedOrder}>
                  <SelectTrigger className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="Y" className="text-xs sm:text-sm">
                      Y
                    </SelectItem>
                    <SelectItem value="N" className="text-xs sm:text-sm">
                      N
                    </SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </div>
            <div>
              <Label className="text-xs sm:text-sm">작업구분</Label>
              <Select value={formWorkType} onValueChange={setFormWorkType}>
                <SelectTrigger className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="내부" className="text-xs sm:text-sm">
                    내부
                  </SelectItem>
                  <SelectItem value="외주" className="text-xs sm:text-sm">
                    외주
                  </SelectItem>
                  <SelectItem value="선택가능" className="text-xs sm:text-sm">
                    선택가능
                  </SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div>
              <Label htmlFor="stdTime" className="text-xs sm:text-sm">
                표준작업시간(분)
              </Label>
              <Input
                id="stdTime"
                type="number"
                min={0}
                step={1}
                value={formStandardTime}
                onChange={(e) => setFormStandardTime(e.target.value)}
                placeholder="0"
                className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm"
              />
            </div>
            {showOutsourceField && (
              <div>
                <Label htmlFor="outsource" className="text-xs sm:text-sm">
                  외주업체
                </Label>
                <Input
                  id="outsource"
                  value={formOutsource}
                  onChange={(e) => setFormOutsource(e.target.value)}
                  placeholder="외주 업체명"
                  className="focus-visible:ring-ring mt-1.5 h-8 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:text-sm"
                />
              </div>
            )}
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              onClick={() => setDetailDialogOpen(false)}
              className="focus-visible:ring-ring h-8 flex-1 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:flex-none sm:text-sm"
            >
              취소
            </Button>
            <Button
              type="button"
              onClick={submitDetailForm}
              disabled={detailSubmitting}
              className="focus-visible:ring-ring h-8 flex-1 text-xs focus-visible:ring-2 focus-visible:ring-offset-2 sm:h-10 sm:flex-none sm:text-sm"
            >
              {detailSubmitting ? <Loader2 className="h-4 w-4 animate-spin" /> : "확인"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 품목 등록 모달 */}
      <Dialog open={registerDialogOpen} onOpenChange={setRegisterDialogOpen}>
        <DialogContent className="max-w-[95vw] sm:max-w-[600px]">
          <DialogHeader>
            <DialogTitle className="text-base sm:text-lg">품목 등록</DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">
              라우팅에 추가할 품목을 검색하고 선택하세요.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-3">
            <div className="relative">
              <Search className="text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 h-3.5 w-3.5 -translate-y-1/2" />
              <Input
                value={registerSearch}
                onChange={(e) => setRegisterSearch(e.target.value)}
                placeholder="품목코드 / 품목명으로 검색"
                className="h-8 pl-8 text-xs sm:h-10 sm:pl-9 sm:text-sm"
                aria-label="품목 검색"
              />
            </div>
            <div className="max-h-[300px] overflow-y-auto rounded-md border">
              {registerLoading ? (
                <div className="text-muted-foreground flex h-32 items-center justify-center gap-2 text-xs sm:text-sm">
                  <Loader2 className="text-primary h-5 w-5 animate-spin" />
                  검색 중...
                </div>
              ) : registerItems.length === 0 ? (
                <p className="text-muted-foreground py-8 text-center text-xs sm:text-sm">
                  {registerSearchDebounced ? "검색 결과가 없습니다." : "품목을 검색하세요."}
                </p>
              ) : (
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-10 text-center">
                        <Checkbox
                          checked={
                            registerItems.filter((ri) => !registeredItemCodes.has(ri.item_number)).length > 0 &&
                            registerItems
                              .filter((ri) => !registeredItemCodes.has(ri.item_number))
                              .every((ri) => registerSelectedIds.has(ri.id))
                          }
                          onCheckedChange={(checked) => {
                            const next = new Set(registerSelectedIds);
                            const available = registerItems.filter((ri) => !registeredItemCodes.has(ri.item_number));
                            if (checked) {
                              available.forEach((ri) => next.add(ri.id));
                            } else {
                              available.forEach((ri) => next.delete(ri.id));
                            }
                            setRegisterSelectedIds(next);
                          }}
                        />
                      </TableHead>
                      <TableHead className="text-xs sm:text-sm">품목코드</TableHead>
                      <TableHead className="text-xs sm:text-sm">품목명</TableHead>
                      <TableHead className="text-xs sm:text-sm">상태</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {registerItems.map((ri) => {
                      const alreadyRegistered = registeredItemCodes.has(ri.item_number);
                      return (
                        <TableRow
                          key={ri.id}
                          className={cn(alreadyRegistered && "opacity-50")}
                        >
                          <TableCell className="text-center">
                            <Checkbox
                              checked={registerSelectedIds.has(ri.id)}
                              disabled={alreadyRegistered}
                              onCheckedChange={(checked) => {
                                const next = new Set(registerSelectedIds);
                                if (checked) next.add(ri.id);
                                else next.delete(ri.id);
                                setRegisterSelectedIds(next);
                              }}
                            />
                          </TableCell>
                          <TableCell className="text-xs sm:text-sm">{ri.item_number}</TableCell>
                          <TableCell className="text-xs sm:text-sm">{ri.item_name}</TableCell>
                          <TableCell className="text-xs sm:text-sm">
                            {alreadyRegistered ? (
                              <span className="text-muted-foreground">등록됨</span>
                            ) : (
                              <span className="text-primary">미등록</span>
                            )}
                          </TableCell>
                        </TableRow>
                      );
                    })}
                  </TableBody>
                </Table>
              )}
            </div>
            {registerSelectedIds.size > 0 && (
              <p className="text-muted-foreground text-xs">
                {registerSelectedIds.size}건 선택됨
              </p>
            )}
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              type="button"
              variant="outline"
              onClick={() => setRegisterDialogOpen(false)}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              취소
            </Button>
            <Button
              type="button"
              onClick={handleRegisterItems}
              disabled={registerSubmitting || registerSelectedIds.size === 0}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              {registerSubmitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
              등록 ({registerSelectedIds.size}건)
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
