"use client";

import React, { useState, useCallback, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Plus, Save, ListOrdered } from "lucide-react";
import { toast } from "sonner";
import { showErrorToast } from "@/lib/utils/toastUtils";
import { NumberingRuleConfig, NumberingRulePart, SEPARATOR_OPTIONS, SeparatorType } from "@/types/numbering-rule";
import { CODE_PART_TYPE_OPTIONS } from "@/types/numbering-rule";
import { NumberingRuleCard } from "./NumberingRuleCard";
import { NumberingRulePreview, computePartDisplayItems, getPartTypeColorClass } from "./NumberingRulePreview";
import { getNumberingRules, saveNumberingRuleToTest } from "@/lib/api/numberingRule";
import { cn } from "@/lib/utils";

interface NumberingRuleDesignerProps {
  initialConfig?: NumberingRuleConfig;
  onSave?: (config: NumberingRuleConfig) => void;
  onChange?: (config: NumberingRuleConfig) => void;
  maxRules?: number;
  isPreview?: boolean;
  className?: string;
  currentTableName?: string;
  menuObjid?: number;
}

export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
  initialConfig,
  onSave,
  onChange,
  maxRules = 6,
  isPreview = false,
  className = "",
  currentTableName,
  menuObjid,
}) => {
  const [rulesList, setRulesList] = useState<NumberingRuleConfig[]>([]);
  const [selectedRuleId, setSelectedRuleId] = useState<string | null>(null);
  const [currentRule, setCurrentRule] = useState<NumberingRuleConfig | null>(null);
  const [selectedPartOrder, setSelectedPartOrder] = useState<number | null>(null);
  const [loading, setLoading] = useState(false);
  const [separatorTypes, setSeparatorTypes] = useState<Record<number, SeparatorType>>({});
  const [customSeparators, setCustomSeparators] = useState<Record<number, string>>({});

  const selectedRule = rulesList.find((r) => r.ruleId === selectedRuleId) ?? currentRule;

  // 좌측: 규칙 목록 로드
  useEffect(() => {
    loadRules();
  }, []);

  const loadRules = async () => {
    setLoading(true);
    try {
      const response = await getNumberingRules();
      if (response.success && response.data) {
        setRulesList(response.data);
        if (response.data.length > 0 && !selectedRuleId) {
          const first = response.data[0];
          setSelectedRuleId(first.ruleId);
          setCurrentRule(JSON.parse(JSON.stringify(first)));
        }
      }
    } catch (e) {
      console.error("채번 규칙 목록 로드 실패:", e);
    } finally {
      setLoading(false);
    }
  };

  const handleSelectRule = (rule: NumberingRuleConfig) => {
    setSelectedRuleId(rule.ruleId);
    setCurrentRule(JSON.parse(JSON.stringify(rule)));
    setSelectedPartOrder(null);
  };

  const handleAddNewRule = () => {
    const newRule: NumberingRuleConfig = {
      ruleId: `rule-${Date.now()}`,
      ruleName: "새 규칙",
      parts: [],
      separator: "-",
      resetPeriod: "none",
      currentSequence: 1,
      scopeType: "global",
      tableName: currentTableName ?? "",
      columnName: "",
    };
    setRulesList((prev) => [...prev, newRule]);
    setSelectedRuleId(newRule.ruleId);
    setCurrentRule(JSON.parse(JSON.stringify(newRule)));
    setSelectedPartOrder(null);
    toast.success("새 규칙이 추가되었습니다");
  };

  useEffect(() => {
    if (currentRule) onChange?.(currentRule);
  }, [currentRule, onChange]);

  useEffect(() => {
    if (currentRule && currentRule.parts.length > 0) {
      const newSepTypes: Record<number, SeparatorType> = {};
      const newCustomSeps: Record<number, string> = {};
      currentRule.parts.forEach((part) => {
        const sep = part.separatorAfter ?? currentRule.separator ?? "-";
        if (sep === "") {
          newSepTypes[part.order] = "none";
          newCustomSeps[part.order] = "";
        } else {
          const opt = SEPARATOR_OPTIONS.find(
            (o) => o.value !== "custom" && o.value !== "none" && o.displayValue === sep
          );
          if (opt) {
            newSepTypes[part.order] = opt.value;
            newCustomSeps[part.order] = "";
          } else {
            newSepTypes[part.order] = "custom";
            newCustomSeps[part.order] = sep;
          }
        }
      });
      setSeparatorTypes(newSepTypes);
      setCustomSeparators(newCustomSeps);
    }
  }, [currentRule?.ruleId]);

  const handlePartSeparatorChange = useCallback((partOrder: number, type: SeparatorType) => {
    setSeparatorTypes((prev) => ({ ...prev, [partOrder]: type }));
    if (type !== "custom") {
      const option = SEPARATOR_OPTIONS.find((opt) => opt.value === type);
      const newSeparator = option?.displayValue ?? "";
      setCustomSeparators((prev) => ({ ...prev, [partOrder]: "" }));
      setCurrentRule((prev) => {
        if (!prev) return null;
        return {
          ...prev,
          parts: prev.parts.map((p) => (p.order === partOrder ? { ...p, separatorAfter: newSeparator } : p)),
        };
      });
    }
  }, []);

  const handlePartCustomSeparatorChange = useCallback((partOrder: number, value: string) => {
    const trimmedValue = value.slice(0, 2);
    setCustomSeparators((prev) => ({ ...prev, [partOrder]: trimmedValue }));
    setCurrentRule((prev) => {
      if (!prev) return null;
      return {
        ...prev,
        parts: prev.parts.map((p) => (p.order === partOrder ? { ...p, separatorAfter: trimmedValue } : p)),
      };
    });
  }, []);

  const handleAddPart = useCallback(() => {
    if (!currentRule) return;
    if (currentRule.parts.length >= maxRules) {
      toast.error(`최대 ${maxRules}개까지 추가할 수 있습니다`);
      return;
    }
    const newPart: NumberingRulePart = {
      id: `part-${Date.now()}`,
      order: currentRule.parts.length + 1,
      partType: "text",
      generationMethod: "auto",
      autoConfig: { textValue: "CODE" },
      separatorAfter: "-",
    };
    setCurrentRule((prev) => (prev ? { ...prev, parts: [...prev.parts, newPart] } : null));
    setSeparatorTypes((prev) => ({ ...prev, [newPart.order]: "-" }));
    setCustomSeparators((prev) => ({ ...prev, [newPart.order]: "" }));
    toast.success(`규칙 ${newPart.order}가 추가되었습니다`);
  }, [currentRule, maxRules]);

  const handleUpdatePart = useCallback((partOrder: number, updates: Partial<NumberingRulePart>) => {
    setCurrentRule((prev) => {
      if (!prev) return null;
      return {
        ...prev,
        parts: prev.parts.map((p) => (p.order === partOrder ? { ...p, ...updates } : p)),
      };
    });
  }, []);

  const handleDeletePart = useCallback((partOrder: number) => {
    setCurrentRule((prev) => {
      if (!prev) return null;
      return {
        ...prev,
        parts: prev.parts
          .filter((p) => p.order !== partOrder)
          .map((p, i) => ({ ...p, order: i + 1 })),
      };
    });
    setSelectedPartOrder(null);
    toast.success("규칙이 삭제되었습니다");
  }, []);

  const handleSave = useCallback(async () => {
    if (!currentRule) {
      toast.error("저장할 규칙이 없습니다");
      return;
    }
    if (currentRule.parts.length === 0) {
      toast.error("최소 1개 이상의 규칙을 추가해주세요");
      return;
    }
    setLoading(true);
    try {
      const defaultAutoConfigs: Record<string, any> = {
        sequence: { sequenceLength: 3, startFrom: 1 },
        number: { numberLength: 4, numberValue: 1 },
        date: { dateFormat: "YYYYMMDD" },
        text: { textValue: "" },
      };
      const partsWithDefaults = currentRule.parts.map((part) => {
        if (part.generationMethod === "auto") {
          const defaults = defaultAutoConfigs[part.partType] || {};
          return { ...part, autoConfig: { ...defaults, ...part.autoConfig } };
        }
        return part;
      });
      const ruleToSave = {
        ...currentRule,
        parts: partsWithDefaults,
        scopeType: "global" as const,
        tableName: currentRule.tableName || currentTableName || "",
        columnName: currentRule.columnName || "",
      };
      const response = await saveNumberingRuleToTest(ruleToSave);
      if (response.success && response.data) {
        const saved: NumberingRuleConfig = JSON.parse(JSON.stringify(response.data));
        setCurrentRule(saved);
        setRulesList((prev) => {
          const idx = prev.findIndex((r) => r.ruleId === currentRule.ruleId);
          if (idx >= 0) {
            const next = [...prev];
            next[idx] = saved;
            return next;
          }
          return [...prev, saved];
        });
        setSelectedRuleId(saved.ruleId);
        await onSave?.(response.data);
        toast.success("채번 규칙이 저장되었습니다");
      } else {
        showErrorToast("채번 규칙 저장에 실패했습니다", response.error, {
          guidance: "설정을 확인하고 다시 시도해 주세요.",
        });
      }
    } catch (error: unknown) {
      showErrorToast("채번 규칙 저장에 실패했습니다", error, {
        guidance: "설정을 확인하고 다시 시도해 주세요.",
      });
    } finally {
      setLoading(false);
    }
  }, [currentRule, onSave, currentTableName]);

  const selectedPart = currentRule?.parts.find((p) => p.order === selectedPartOrder) ?? null;
  const globalSep = currentRule?.separator ?? "-";
  const partItems = currentRule ? computePartDisplayItems(currentRule) : [];

  return (
    <div className={cn("flex h-full gap-4", className)}>
      {/* 좌측: 규칙 리스트 (code-nav, 220px) */}
      <div className="code-nav flex w-[220px] flex-shrink-0 flex-col gap-3">
        <div className="flex items-center justify-between gap-2">
          <div className="flex items-center gap-2">
            <ListOrdered className="h-4 w-4 text-muted-foreground" />
            <span className="text-sm font-semibold">채번 규칙 ({rulesList.length})</span>
          </div>
          <Button
            size="sm"
            className="h-8 gap-1 text-xs font-medium"
            onClick={handleAddNewRule}
            disabled={isPreview || loading}
          >
            <Plus className="h-3.5 w-3.5" />
            추가
          </Button>
        </div>
        <div className="flex-1 space-y-0.5 overflow-y-auto">
          {loading && rulesList.length === 0 ? (
            <div className="flex h-24 items-center justify-center text-xs text-muted-foreground">
              로딩 중...
            </div>
          ) : rulesList.length === 0 ? (
            <div className="flex h-24 items-center justify-center rounded-lg border border-dashed border-border bg-muted/50 text-xs text-muted-foreground">
              규칙이 없습니다
            </div>
          ) : (
            rulesList.map((rule) => {
              const isSelected = selectedRuleId === rule.ruleId;
              return (
                <button
                  key={rule.ruleId}
                  type="button"
                  className={cn(
                    "code-nav-item flex w-full flex-col items-start gap-0.5 rounded-md px-3 py-2 text-left transition-colors",
                    isSelected
                      ? "border-l-[3px] border-primary bg-primary/5 font-bold"
                      : "hover:bg-accent"
                  )}
                  onClick={() => handleSelectRule(rule)}
                >
                  <span className="rule-name min-w-0 truncate text-xs">{rule.ruleName}</span>
                  <span className="rule-table text-[9px] text-muted-foreground">
                    {rule.tableName || "-"}
                  </span>
                  <span className="mt-0.5 inline-flex">
                    <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
                      {rule.parts?.length ?? 0}개
                    </span>
                  </span>
                </button>
              );
            })
          )}
        </div>
      </div>

      <div className="h-full w-px flex-shrink-0 bg-border" />

      {/* 우측: 미리보기 + 파이프라인 + 설정 + 저장 바 */}
      <div className="flex flex-1 flex-col gap-4 overflow-hidden">
        {!currentRule ? (
          <div className="flex flex-1 flex-col items-center justify-center text-center">
            <ListOrdered className="mb-3 h-10 w-10 text-muted-foreground" />
            <p className="mb-2 text-lg font-medium text-muted-foreground">규칙을 선택하세요</p>
            <p className="text-sm text-muted-foreground">
              좌측에서 채번 규칙을 선택하거나 &quot;추가&quot;로 새 규칙을 만드세요
            </p>
          </div>
        ) : (
          <>
            <div className="flex flex-col gap-2">
              <Label className="text-xs font-medium">규칙명</Label>
              <Input
                value={currentRule.ruleName}
                onChange={(e) => setCurrentRule((prev) => (prev ? { ...prev, ruleName: e.target.value } : null))}
                placeholder="예: 프로젝트 코드"
                className="h-9 text-sm"
              />
            </div>

            {/* 큰 미리보기 스트립 (code-preview-strip) */}
            <div className="code-preview-strip flex-shrink-0">
              <NumberingRulePreview config={currentRule} variant="strip" />
            </div>

            {/* 파이프라인 영역 (code-pipeline-area) */}
            <div className="code-pipeline-area flex flex-col gap-2">
              <div className="flex items-center justify-between">
                <span className="text-xs font-semibold text-muted-foreground">코드 구성</span>
                <span className="text-xs text-muted-foreground">
                  {currentRule.parts.length}/{maxRules}
                </span>
              </div>
              <div className="flex flex-1 flex-wrap items-center gap-2 overflow-x-auto overflow-y-hidden py-1">
                {currentRule.parts.length === 0 ? (
                  <div className="flex h-24 min-w-[200px] items-center justify-center rounded-xl border-2 border-dashed border-border bg-muted/30 text-xs text-muted-foreground">
                    규칙을 추가하여 코드를 구성하세요
                  </div>
                ) : (
                  <>
                    {currentRule.parts.map((part, index) => {
                      const item = partItems.find((i) => i.order === part.order);
                      const sep = part.separatorAfter ?? globalSep;
                      const isSelected = selectedPartOrder === part.order;
                      const typeLabel = CODE_PART_TYPE_OPTIONS.find((o) => o.value === part.partType)?.label ?? part.partType;
                      return (
                        <React.Fragment key={`part-${part.order}-${index}`}>
                          <button
                            type="button"
                            className={cn(
                              "pipe-segment min-w-[120px] rounded-[10px] border-2 px-3 py-3 text-left transition-all",
                              part.partType === "date" && "border-warning",
                              part.partType === "text" && "border-primary",
                              part.partType === "sequence" && "border-primary",
                              (part.partType === "number" || part.partType === "category" || part.partType === "reference") && "border-border",
                              isSelected && "border-primary bg-primary/5 shadow-md ring-2 ring-primary/30"
                            )}
                            onClick={() => setSelectedPartOrder(part.order)}
                          >
                            <div className="text-[10px] font-medium text-muted-foreground">{typeLabel}</div>
                            <div className={cn("mt-0.5 truncate font-mono text-sm font-medium", getPartTypeColorClass(part.partType))}>
                              {item?.displayValue ?? "-"}
                            </div>
                          </button>
                          {index < currentRule.parts.length - 1 && (
                            <span className="flex items-center gap-1 text-muted-foreground">
                              <span className="text-xs">→</span>
                              <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] font-mono">
                                {sep || "(없음)"}
                              </span>
                            </span>
                          )}
                        </React.Fragment>
                      );
                    })}
                    <button
                      type="button"
                      className="flex h-[52px] w-10 flex-shrink-0 items-center justify-center rounded-full border-2 border-dashed border-border text-muted-foreground transition-colors hover:border-primary hover:bg-primary/5 hover:text-primary"
                      onClick={handleAddPart}
                      disabled={currentRule.parts.length >= maxRules || isPreview || loading}
                      aria-label="규칙 추가"
                    >
                      <Plus className="h-5 w-5" />
                    </button>
                  </>
                )}
              </div>
            </div>

            {/* 설정 패널 (선택된 세그먼트 상세, code-config-panel) */}
            {selectedPart && (
              <div className="code-config-panel min-h-0 flex-1 overflow-y-auto rounded-lg bg-muted/30 p-4">
                <div className="grid grid-cols-[repeat(auto-fill,minmax(180px,1fr))] gap-3">
                  <NumberingRuleCard
                    part={selectedPart}
                    onUpdate={(updates) => handleUpdatePart(selectedPart.order, updates)}
                    onDelete={() => handleDeletePart(selectedPart.order)}
                    isPreview={isPreview}
                    tableName={currentRule.tableName ?? currentTableName}
                  />
                </div>
                {currentRule.parts.some((p) => p.order === selectedPart.order) && (
                  <div className="mt-3 flex items-center gap-2">
                    <span className="text-[10px] text-muted-foreground">뒤 구분자</span>
                    <Select
                      value={separatorTypes[selectedPart.order] ?? "-"}
                      onValueChange={(v) => handlePartSeparatorChange(selectedPart.order, v as SeparatorType)}
                    >
                      <SelectTrigger className="h-7 w-24 text-xs">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        {SEPARATOR_OPTIONS.map((opt) => (
                          <SelectItem key={opt.value} value={opt.value} className="text-xs">
                            {opt.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                    {separatorTypes[selectedPart.order] === "custom" && (
                      <Input
                        value={customSeparators[selectedPart.order] ?? ""}
                        onChange={(e) => handlePartCustomSeparatorChange(selectedPart.order, e.target.value)}
                        className="h-7 w-14 text-center text-[10px]"
                        placeholder="2자"
                        maxLength={2}
                      />
                    )}
                  </div>
                )}
              </div>
            )}

            {/* 저장 바 (code-save-bar) */}
            <div className="code-save-bar flex flex-shrink-0 items-center justify-between gap-4 border-t border-border pt-4">
              <div className="min-w-0 flex-1 text-xs text-muted-foreground">
                {currentRule.tableName && (
                  <span>테이블: {currentRule.tableName}</span>
                )}
                {currentRule.columnName && (
                  <span className="ml-2">컬럼: {currentRule.columnName}</span>
                )}
                <span className="ml-2">구분자: {globalSep || "-"}</span>
                {currentRule.resetPeriod && currentRule.resetPeriod !== "none" && (
                  <span className="ml-2">리셋: {currentRule.resetPeriod}</span>
                )}
              </div>
              <Button
                onClick={handleSave}
                disabled={isPreview || loading}
                className="h-9 gap-2 text-sm font-medium"
              >
                <Save className="h-4 w-4" />
                {loading ? "저장 중..." : "저장"}
              </Button>
            </div>
          </>
        )}
      </div>
    </div>
  );
};
