"use client";

import React, { useState, useRef, useCallback } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { toast } from "sonner";
import {
  Upload,
  FileSpreadsheet,
  AlertCircle,
  CheckCircle2,
  Download,
  Loader2,
  X,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { importFromExcel } from "@/lib/utils/excelExport";
import { apiClient } from "@/lib/api/client";

interface BomExcelUploadModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSuccess?: () => void;
  /** bomId가 있으면 "새 버전 등록" 모드, 없으면 "새 BOM 생성" 모드 */
  bomId?: string;
  bomName?: string;
}

interface ParsedRow {
  rowIndex: number;
  level: number;
  item_number: string;
  item_name: string;
  quantity: number;
  unit: string;
  process_type: string;
  remark: string;
  valid: boolean;
  error?: string;
  isHeader?: boolean;
}

type UploadStep = "upload" | "preview" | "result";

const EXPECTED_HEADERS = ["레벨", "품번", "품명", "소요량", "단위", "공정구분", "비고"];

const HEADER_MAP: Record<string, string> = {
  "레벨": "level",
  "level": "level",
  "품번": "item_number",
  "품목코드": "item_number",
  "item_number": "item_number",
  "item_code": "item_number",
  "품명": "item_name",
  "품목명": "item_name",
  "item_name": "item_name",
  "소요량": "quantity",
  "수량": "quantity",
  "quantity": "quantity",
  "qty": "quantity",
  "단위": "unit",
  "unit": "unit",
  "공정구분": "process_type",
  "공정": "process_type",
  "process_type": "process_type",
  "비고": "remark",
  "remark": "remark",
};

export function BomExcelUploadModal({
  open,
  onOpenChange,
  onSuccess,
  bomId,
  bomName,
}: BomExcelUploadModalProps) {
  const isVersionMode = !!bomId;

  const [step, setStep] = useState<UploadStep>("upload");
  const [parsedRows, setParsedRows] = useState<ParsedRow[]>([]);
  const [fileName, setFileName] = useState<string>("");
  const [uploading, setUploading] = useState(false);
  const [uploadResult, setUploadResult] = useState<any>(null);
  const [downloading, setDownloading] = useState(false);
  const [versionName, setVersionName] = useState<string>("");
  const fileInputRef = useRef<HTMLInputElement>(null);

  const reset = useCallback(() => {
    setStep("upload");
    setParsedRows([]);
    setFileName("");
    setUploadResult(null);
    setUploading(false);
    setVersionName("");
    if (fileInputRef.current) fileInputRef.current.value = "";
  }, []);

  const handleClose = useCallback(() => {
    reset();
    onOpenChange(false);
  }, [reset, onOpenChange]);

  const handleFileSelect = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    setFileName(file.name);

    try {
      const rawData = await importFromExcel(file);
      if (!rawData || rawData.length === 0) {
        toast.error("엑셀 파일에 데이터가 없습니다");
        return;
      }

      const firstRow = rawData[0];
      const excelHeaders = Object.keys(firstRow);
      const fieldMap: Record<string, string> = {};

      for (const header of excelHeaders) {
        const normalized = header.trim().toLowerCase();
        const mapped = HEADER_MAP[normalized] || HEADER_MAP[header.trim()];
        if (mapped) {
          fieldMap[header] = mapped;
        }
      }

      const hasItemNumber = excelHeaders.some(h => {
        const n = h.trim().toLowerCase();
        return HEADER_MAP[n] === "item_number" || HEADER_MAP[h.trim()] === "item_number";
      });
      if (!hasItemNumber) {
        toast.error("품번 컬럼을 찾을 수 없습니다. 컬럼명을 확인해주세요.");
        return;
      }

      const parsed: ParsedRow[] = [];
      for (let index = 0; index < rawData.length; index++) {
        const row = rawData[index];
        const getField = (fieldName: string): any => {
          for (const [excelKey, mappedField] of Object.entries(fieldMap)) {
            if (mappedField === fieldName) return row[excelKey];
          }
          return undefined;
        };

        const levelRaw = getField("level");
        const level = typeof levelRaw === "number" ? levelRaw : parseInt(String(levelRaw || "0"), 10);
        const itemNumber = String(getField("item_number") || "").trim();
        const itemName = String(getField("item_name") || "").trim();
        const quantityRaw = getField("quantity");
        const quantity = typeof quantityRaw === "number" ? quantityRaw : parseFloat(String(quantityRaw || "1"));
        const unit = String(getField("unit") || "").trim();
        const processType = String(getField("process_type") || "").trim();
        const remark = String(getField("remark") || "").trim();

        let valid = true;
        let error = "";
        const isHeader = level === 0;

        if (!itemNumber) {
          valid = false;
          error = "품번 필수";
        } else if (isNaN(level) || level < 0) {
          valid = false;
          error = "레벨 오류";
        } else if (index > 0) {
          const prevLevel = parsed[index - 1]?.level ?? 0;
          if (level > prevLevel + 1) {
            valid = false;
            error = `레벨 점프 (이전: ${prevLevel})`;
          }
        }

        parsed.push({
          rowIndex: index + 1,
          isHeader,
          level,
          item_number: itemNumber,
          item_name: itemName,
          quantity: isNaN(quantity) ? 1 : quantity,
          unit,
          process_type: processType,
          remark,
          valid,
          error,
        });
      }

      const filtered = parsed.filter(r => r.item_number !== "");

      // 새 BOM 생성 모드: 레벨 0 필수
      if (!isVersionMode) {
        const hasHeader = filtered.some(r => r.level === 0);
        if (!hasHeader) {
          toast.error("레벨 0(BOM 마스터) 행이 필요합니다. 첫 행에 최상위 품목을 입력해주세요.");
          return;
        }
      }

      setParsedRows(filtered);
      setStep("preview");
    } catch (err: any) {
      toast.error(`파일 파싱 실패: ${err.message}`);
    }
  }, [isVersionMode]);

  const handleUpload = useCallback(async () => {
    const invalidRows = parsedRows.filter(r => !r.valid);
    if (invalidRows.length > 0) {
      toast.error(`유효하지 않은 행이 ${invalidRows.length}건 있습니다.`);
      return;
    }

    setUploading(true);
    try {
      const rowPayload = parsedRows.map(r => ({
        level: r.level,
        item_number: r.item_number,
        item_name: r.item_name,
        quantity: r.quantity,
        unit: r.unit,
        process_type: r.process_type,
        remark: r.remark,
      }));

      let res;
      if (isVersionMode) {
        res = await apiClient.post(`/bom/${bomId}/excel-upload-version`, {
          rows: rowPayload,
          versionName: versionName.trim() || undefined,
        });
      } else {
        res = await apiClient.post("/bom/excel-upload", { rows: rowPayload });
      }

      if (res.data?.success) {
        setUploadResult(res.data.data);
        setStep("result");
        const msg = isVersionMode
          ? `새 버전 생성 완료: 하위품목 ${res.data.data.insertedCount}건`
          : `BOM 생성 완료: 하위품목 ${res.data.data.insertedCount}건`;
        toast.success(msg);
        onSuccess?.();
      } else {
        const errData = res.data?.data;
        if (errData?.unmatchedItems?.length > 0) {
          toast.error(`매칭 안 되는 품번: ${errData.unmatchedItems.join(", ")}`);
          setParsedRows(prev => prev.map(r => {
            if (errData.unmatchedItems.includes(r.item_number)) {
              return { ...r, valid: false, error: "품번 미등록" };
            }
            return r;
          }));
        } else {
          toast.error(res.data?.message || "업로드 실패");
        }
      }
    } catch (err: any) {
      toast.error(`업로드 오류: ${err.response?.data?.message || err.message}`);
    } finally {
      setUploading(false);
    }
  }, [parsedRows, isVersionMode, bomId, versionName, onSuccess]);

  const handleDownloadTemplate = useCallback(async () => {
    setDownloading(true);
    try {
      const XLSX = await import("xlsx");
      let data: Record<string, any>[] = [];

      if (isVersionMode && bomId) {
        // 기존 BOM 데이터를 템플릿으로 다운로드
        try {
          const res = await apiClient.get(`/bom/${bomId}/excel-download`);
          if (res.data?.success && res.data.data?.length > 0) {
            data = res.data.data.map((row: any) => ({
              "레벨": row.level,
              "품번": row.item_number,
              "품명": row.item_name,
              "소요량": row.quantity,
              "단위": row.unit,
              "공정구분": row.process_type,
              "비고": row.remark,
            }));
          }
        } catch { /* 데이터 없으면 빈 템플릿 */ }
      }

      if (data.length === 0) {
        if (isVersionMode) {
          data = [
            { "레벨": 1, "품번": "(자품목 품번)", "품명": "(자품목 품명)", "소요량": 2, "단위": "EA", "공정구분": "", "비고": "" },
            { "레벨": 2, "품번": "(하위품목 품번)", "품명": "(하위 품명)", "소요량": 1, "단위": "EA", "공정구분": "", "비고": "" },
          ];
        } else {
          data = [
            { "레벨": 0, "품번": "(최상위 품번)", "품명": "(최상위 품명)", "소요량": 1, "단위": "EA", "공정구분": "", "비고": "BOM 마스터" },
            { "레벨": 1, "품번": "(자품목 품번)", "품명": "(자품목 품명)", "소요량": 2, "단위": "EA", "공정구분": "", "비고": "" },
            { "레벨": 2, "품번": "(하위품목 품번)", "품명": "(하위 품명)", "소요량": 1, "단위": "EA", "공정구분": "", "비고": "" },
          ];
        }
      }

      const ws = XLSX.utils.json_to_sheet(data);
      const wb = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(wb, ws, "BOM");
      ws["!cols"] = [
        { wch: 6 }, { wch: 18 }, { wch: 20 }, { wch: 10 },
        { wch: 8 }, { wch: 12 }, { wch: 20 },
      ];

      const filename = bomName ? `BOM_${bomName}.xlsx` : "BOM_template.xlsx";
      XLSX.writeFile(wb, filename);
      toast.success("템플릿 다운로드 완료");
    } catch (err: any) {
      toast.error(`다운로드 실패: ${err.message}`);
    } finally {
      setDownloading(false);
    }
  }, [isVersionMode, bomId, bomName]);

  const headerRow = parsedRows.find(r => r.isHeader);
  const detailRows = parsedRows.filter(r => !r.isHeader);
  const validCount = parsedRows.filter(r => r.valid).length;
  const invalidCount = parsedRows.filter(r => !r.valid).length;

  const title = isVersionMode ? "BOM 새 버전 엑셀 업로드" : "BOM 엑셀 업로드";
  const description = isVersionMode
    ? `${bomName || "선택된 BOM"}의 새 버전을 엑셀 파일로 생성합니다. 레벨 0 행은 건너뜁니다.`
    : "엑셀 파일로 새 BOM을 생성합니다. 레벨 0 = BOM 마스터, 레벨 1 이상 = 하위품목.";

  return (
    <Dialog open={open} onOpenChange={(v) => { if (!v) handleClose(); }}>
      <DialogContent className="max-w-[95vw] sm:max-w-[800px] max-h-[90vh] overflow-hidden flex flex-col">
        <DialogHeader>
          <DialogTitle className="text-base sm:text-lg">{title}</DialogTitle>
          <DialogDescription className="text-xs sm:text-sm">{description}</DialogDescription>
        </DialogHeader>

        {/* Step 1: 파일 업로드 */}
        {step === "upload" && (
          <div className="space-y-4">
            {/* 새 버전 모드: 버전명 입력 */}
            {isVersionMode && (
              <div>
                <Label className="text-xs sm:text-sm">버전명 (미입력 시 자동 채번)</Label>
                <Input
                  value={versionName}
                  onChange={(e) => setVersionName(e.target.value)}
                  placeholder="예: 2.0"
                  className="h-8 text-xs sm:h-10 sm:text-sm mt-1"
                />
              </div>
            )}

            <div
              className={cn(
                "border-2 border-dashed rounded-lg p-8 text-center cursor-pointer",
                "hover:border-primary/50 hover:bg-muted/50 transition-colors",
                "border-muted-foreground/25",
              )}
              onClick={() => fileInputRef.current?.click()}
            >
              <FileSpreadsheet className="mx-auto h-10 w-10 text-muted-foreground mb-3" />
              <p className="text-sm font-medium">엑셀 파일을 선택하세요</p>
              <p className="text-xs text-muted-foreground mt-1">.xlsx, .xls, .csv 형식 지원</p>
              <input
                ref={fileInputRef}
                type="file"
                accept=".xlsx,.xls,.csv"
                className="hidden"
                onChange={handleFileSelect}
              />
            </div>

            <div className="rounded-md bg-muted/50 p-3">
              <p className="text-xs font-medium mb-2">엑셀 컬럼 형식</p>
              <div className="flex flex-wrap gap-1">
                {EXPECTED_HEADERS.map((h, i) => (
                  <span
                    key={h}
                    className={cn(
                      "text-[10px] px-2 py-0.5 rounded-full",
                      i < 2 ? "bg-primary/10 text-primary font-medium" : "bg-muted text-muted-foreground",
                    )}
                  >
                    {h}{i < 2 ? " *" : ""}
                  </span>
                ))}
              </div>
              <p className="text-[10px] text-muted-foreground mt-1.5">
                {isVersionMode
                  ? "* 레벨 1 = 직접 자품목, 레벨 2 = 자품목의 자품목. 레벨 0 행이 있으면 건너뜁니다."
                  : "* 레벨 0 = BOM 마스터(최상위 품목, 1행), 레벨 1 = 직접 자품목, 레벨 2 = 자품목의 자품목."
                }
              </p>
            </div>

            <Button
              variant="outline"
              size="sm"
              onClick={handleDownloadTemplate}
              disabled={downloading}
              className="w-full"
            >
              {downloading ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <Download className="mr-2 h-4 w-4" />
              )}
              {isVersionMode && bomName ? `현재 BOM 데이터로 템플릿 다운로드` : "빈 템플릿 다운로드"}
            </Button>
          </div>
        )}

        {/* Step 2: 미리보기 */}
        {step === "preview" && (
          <div className="flex flex-col flex-1 min-h-0 space-y-3">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-3">
                <span className="text-xs text-muted-foreground">{fileName}</span>
                {!isVersionMode && headerRow && (
                  <span className="text-xs font-medium">마스터: {headerRow.item_number}</span>
                )}
                <span className="text-xs">
                  하위품목 <span className="font-medium">{detailRows.length}</span>건
                </span>
                {invalidCount > 0 && (
                  <span className="text-xs text-destructive flex items-center gap-1">
                    <AlertCircle className="h-3 w-3" /> {invalidCount}건 오류
                  </span>
                )}
              </div>
              <Button variant="ghost" size="sm" onClick={reset} className="h-7 text-xs">
                <X className="h-3 w-3 mr-1" />
                다시 선택
              </Button>
            </div>

            <div className="flex-1 min-h-0 overflow-auto border rounded-md">
              <table className="w-full text-xs">
                <thead className="bg-muted/50 sticky top-0">
                  <tr>
                    <th className="px-2 py-1.5 text-left font-medium w-8">#</th>
                    <th className="px-2 py-1.5 text-left font-medium w-12">구분</th>
                    <th className="px-2 py-1.5 text-center font-medium w-12">레벨</th>
                    <th className="px-2 py-1.5 text-left font-medium">품번</th>
                    <th className="px-2 py-1.5 text-left font-medium">품명</th>
                    <th className="px-2 py-1.5 text-right font-medium w-16">소요량</th>
                    <th className="px-2 py-1.5 text-left font-medium w-14">단위</th>
                    <th className="px-2 py-1.5 text-left font-medium w-20">공정</th>
                    <th className="px-2 py-1.5 text-left font-medium">비고</th>
                  </tr>
                </thead>
                <tbody>
                  {parsedRows.map((row) => (
                    <tr
                      key={row.rowIndex}
                      className={cn(
                        "border-t hover:bg-muted/30",
                        row.isHeader && "bg-primary/10/50",
                        !row.valid && "bg-destructive/5",
                      )}
                    >
                      <td className="px-2 py-1 text-muted-foreground">{row.rowIndex}</td>
                      <td className="px-2 py-1">
                        {row.isHeader ? (
                          <span className="text-[10px] text-primary font-medium bg-primary/10 px-1.5 py-0.5 rounded">
                            {isVersionMode ? "건너뜀" : "마스터"}
                          </span>
                        ) : row.valid ? (
                          <CheckCircle2 className="h-3.5 w-3.5 text-emerald-500" />
                        ) : (
                          <span className="flex items-center gap-1" title={row.error}>
                            <AlertCircle className="h-3.5 w-3.5 text-destructive" />
                          </span>
                        )}
                      </td>
                      <td className="px-2 py-1 text-center">
                        <span
                          className={cn(
                            "inline-block rounded px-1.5 py-0.5 text-[10px] font-mono",
                            row.isHeader ? "bg-primary/10 text-primary font-medium" : "bg-muted",
                          )}
                          style={{ marginLeft: `${row.level * 8}px` }}
                        >
                          {row.level}
                        </span>
                      </td>
                      <td className={cn("px-2 py-1 font-mono", row.isHeader && "font-semibold")}>{row.item_number}</td>
                      <td className={cn("px-2 py-1", row.isHeader && "font-semibold")}>{row.item_name}</td>
                      <td className="px-2 py-1 text-right font-mono">{row.quantity}</td>
                      <td className="px-2 py-1">{row.unit}</td>
                      <td className="px-2 py-1">{row.process_type}</td>
                      <td className="px-2 py-1 text-muted-foreground truncate max-w-[100px]">{row.remark}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {invalidCount > 0 && (
              <div className="rounded-md bg-destructive/10 p-2.5 text-xs text-destructive">
                <div className="font-medium mb-1">유효하지 않은 행 ({invalidCount}건)</div>
                <ul className="space-y-0.5 ml-3 list-disc">
                  {parsedRows.filter(r => !r.valid).slice(0, 5).map(r => (
                    <li key={r.rowIndex}>{r.rowIndex}행: {r.error}</li>
                  ))}
                  {invalidCount > 5 && <li>...외 {invalidCount - 5}건</li>}
                </ul>
              </div>
            )}

            <div className="text-xs text-muted-foreground">
              {isVersionMode
                ? "레벨 1 이상의 하위품목으로 새 버전을 생성합니다."
                : "레벨 0 품목으로 새 BOM 마스터를 생성하고, 레벨 1 이상은 하위품목으로 등록합니다."
              }
            </div>
          </div>
        )}

        {/* Step 3: 결과 */}
        {step === "result" && uploadResult && (
          <div className="space-y-4 py-4">
            <div className="flex flex-col items-center text-center">
              <div className="w-14 h-14 rounded-full bg-emerald-100 flex items-center justify-center mb-3">
                <CheckCircle2 className="h-7 w-7 text-emerald-600" />
              </div>
              <h3 className="text-lg font-semibold">
                {isVersionMode ? "새 버전 생성 완료" : "BOM 생성 완료"}
              </h3>
              <p className="text-sm text-muted-foreground mt-1">
                하위품목 {uploadResult.insertedCount}건이 등록되었습니다.
              </p>
            </div>

            <div className={cn("grid gap-3 max-w-xs mx-auto", isVersionMode ? "grid-cols-1" : "grid-cols-2")}>
              {!isVersionMode && (
                <div className="rounded-lg bg-muted/50 p-3 text-center">
                  <div className="text-2xl font-bold text-primary">1</div>
                  <div className="text-xs text-muted-foreground">BOM 마스터</div>
                </div>
              )}
              <div className="rounded-lg bg-muted/50 p-3 text-center">
                <div className="text-2xl font-bold text-emerald-600">{uploadResult.insertedCount}</div>
                <div className="text-xs text-muted-foreground">하위품목</div>
              </div>
            </div>
          </div>
        )}

        <DialogFooter className="gap-2 sm:gap-0">
          {step === "upload" && (
            <Button
              variant="outline"
              onClick={handleClose}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              닫기
            </Button>
          )}
          {step === "preview" && (
            <>
              <Button
                variant="outline"
                onClick={reset}
                className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
              >
                취소
              </Button>
              <Button
                onClick={handleUpload}
                disabled={uploading || invalidCount > 0}
                className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
              >
                {uploading ? (
                  <><Loader2 className="mr-2 h-4 w-4 animate-spin" /> 업로드 중...</>
                ) : (
                  <><Upload className="mr-2 h-4 w-4" />
                    {isVersionMode ? `새 버전 생성 (${detailRows.length}건)` : `BOM 생성 (${detailRows.length}건)`}
                  </>
                )}
              </Button>
            </>
          )}
          {step === "result" && (
            <Button
              onClick={handleClose}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              확인
            </Button>
          )}
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
