"use client";

import React, { useEffect, useMemo, useRef, useState } from "react";
import { previewNumberingCode } from "@/lib/api/numberingRule";

/**
 * NumberingPicker — 채번 코드 picker
 *
 * InvField autonum 의 캔버스 위젯. 운영 모드에서 채번 규칙 API 를 호출해
 * 자동으로 코드를 생성하고, 템플릿에 `____` 가 있으면 사용자 수동입력 분기
 * (prefix span + input + suffix span) 로 렌더.
 *
 * 옛 입력 컴포넌트의 채번 본체 (state/effect/렌더) 를 canonical 로 흡수 (Phase A.6). 차이:
 *  - 디자인 모드 체크 추가 (preview API 미호출)
 *  - props.numberingRuleId 우선 (autoGen.options.numberingRuleId 에서 직접 명시 시)
 *  - by-column API + getTableColumns fallback 흐름 유지
 *
 * 관련: notes/gbpark/2026-05-08-input-canonical-migration.md §A.6
 */
export interface NumberingPickerProps {
  value: unknown;
  onChange: (v: string) => void;
  tableName?: string;
  columnName?: string;
  formData?: Record<string, any>;
  numberingRuleId?: string;
  isEditMode?: boolean;
  isDesignMode?: boolean;
  disabled?: boolean;
  readonly?: boolean;
  placeholder?: string;
  className?: string;
  style?: React.CSSProperties;
  /**
   * ruleId 가 결정 (props 또는 by-column 조회) 되면 1회 호출.
   * EditModal / buttonActions 의 `${columnName}_numberingRuleId` 메타 키 호환용.
   */
  onRuleIdResolved?: (ruleId: string) => void;
}

export const NumberingPicker: React.FC<NumberingPickerProps> = ({
  value,
  onChange,
  tableName,
  columnName,
  formData,
  numberingRuleId: propRuleId,
  isEditMode = false,
  isDesignMode = false,
  disabled = false,
  readonly = false,
  placeholder,
  className,
  style,
  onRuleIdResolved,
}) => {
  // ─── state / refs ──────────────────────────────────────────
  const [autoGeneratedValue, setAutoGeneratedValue] = useState<string | null>(null);
  const [isGenerating, setIsGenerating] = useState(false);
  const [manualInputValue, setManualInputValue] = useState<string>("");

  const ruleIdRef = useRef<string | null>(propRuleId ?? null);
  const hasGeneratedRef = useRef<boolean>(false);
  const lastCategoryValuesRef = useRef<string>("");
  const userEditedRef = useRef<boolean>(false);
  const hadManualPartRef = useRef<boolean>(false);
  const templateRef = useRef<string>("");
  const formDataRef = useRef<Record<string, any> | undefined>(formData);

  // 최신 formData 추적 (effect closure stale 방지)
  useEffect(() => {
    formDataRef.current = formData;
  }, [formData]);

  // props.numberingRuleId 변경 시 ref 갱신 + 외부 알림 (autoGen 설정 변경 대응)
  useEffect(() => {
    if (propRuleId && propRuleId !== ruleIdRef.current) {
      ruleIdRef.current = propRuleId;
      hasGeneratedRef.current = false;
      onRuleIdResolved?.(propRuleId);
    } else if (propRuleId && ruleIdRef.current === propRuleId) {
      // 첫 mount 시 useRef 초기화에서 set 된 케이스
      onRuleIdResolved?.(propRuleId);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [propRuleId]);

  // formData 의 다른 string 필드 변화 추적 (카테고리 기반 채번 재생성용)
  const categoryValuesForNumbering = useMemo(() => {
    if (!formData) return "";
    const categoryFields: Record<string, string> = {};
    for (const [key, val] of Object.entries(formData)) {
      if (key === columnName) continue;
      if (typeof val === "string" && val) {
        categoryFields[key] = val;
      }
    }
    return JSON.stringify(categoryFields);
  }, [formData, columnName]);

  // ─── main effect: ruleId 조회 + preview ────────────────────
  useEffect(() => {
    if (isDesignMode) return;
    if (isEditMode) return; // 수정 모드는 기존 값 유지

    let cancelled = false;

    const run = async () => {
      if (isGenerating) return;

      const categoryChanged = categoryValuesForNumbering !== lastCategoryValuesRef.current;
      if (userEditedRef.current && !categoryChanged) return;
      if (hasGeneratedRef.current && !categoryChanged) return;

      // 첫 생성 시 값이 이미 있고 카테고리 변경이 아니면 스킵
      if (!categoryChanged && value !== undefined && value !== null && value !== "") return;

      setIsGenerating(true);
      try {
        // ruleId 결정 (없을 때만 by-column → fallback 흐름)
        if (!ruleIdRef.current) {
          if (!tableName || !columnName) {
            console.warn("NumberingPicker: tableName/columnName 없음", { tableName, columnName });
            return;
          }
          // by-column API
          try {
            const { apiClient } = await import("@/lib/api/client");
            const ruleResp = await apiClient.get(`/numbering-rules/by-column/${tableName}/${columnName}`);
            if (cancelled) return;
            if (ruleResp.data?.success && ruleResp.data?.data?.ruleId) {
              ruleIdRef.current = ruleResp.data.data.ruleId;
              onRuleIdResolved?.(ruleResp.data.data.ruleId);
            }
          } catch {
            // detailSettings fallback
            try {
              const { getTableColumns } = await import("@/lib/api/tableManagement");
              const colsResp = await getTableColumns(tableName);
              if (cancelled) return;
              if (colsResp.success && colsResp.data) {
                const cols = colsResp.data.columns || colsResp.data;
                const target = cols.find((c: { column_name: string }) => c.column_name === columnName);
                if (target?.detail_settings) {
                  const parsed =
                    typeof target.detail_settings === "string"
                      ? JSON.parse(target.detail_settings)
                      : target.detail_settings;
                  ruleIdRef.current = parsed.numberingRuleId || null;
                  if (ruleIdRef.current) onRuleIdResolved?.(ruleIdRef.current);
                }
              }
            } catch {
              /* ignore */
            }
          }
        }

        const ruleId = ruleIdRef.current;
        if (!ruleId) {
          console.warn("NumberingPicker: 채번 규칙 없음. 옵션설정 > 채번설정에서 생성 필요", {
            tableName,
            columnName,
          });
          return;
        }

        const resp = await previewNumberingCode(ruleId, formDataRef.current, manualInputValue || undefined);
        if (cancelled) return;

        if (resp.success && resp.data?.generatedCode) {
          const code = resp.data.generatedCode;
          hasGeneratedRef.current = true;
          lastCategoryValuesRef.current = categoryValuesForNumbering;

          if (code.includes("____")) {
            hadManualPartRef.current = true;
            const oldTemplate = templateRef.current;
            templateRef.current = code;

            if (!userEditedRef.current) {
              // 첫 생성 — 템플릿 그대로 표시
              setAutoGeneratedValue(code);
              onChange(code);
            } else if (oldTemplate !== code) {
              // 카테고리 변경으로 템플릿 갱신 + 기존 manualInputValue 유지 → 새 조합값 부모에 반영
              const parts = code.split("____");
              const newPrefix = parts[0] || "";
              const newSuffix = parts.length > 1 ? parts.slice(1).join("") : "";
              const newCombined = newPrefix + manualInputValue + newSuffix;
              setAutoGeneratedValue(newCombined);
              onChange(newCombined);
            }
          } else {
            hadManualPartRef.current = false;
            templateRef.current = "";
            setAutoGeneratedValue(code);
            onChange(code);
            userEditedRef.current = false;
          }
        } else {
          console.warn("NumberingPicker: 채번 코드 생성 실패", resp);
        }
      } catch (err) {
        if (!cancelled) console.error("NumberingPicker: 자동생성 오류", err);
      } finally {
        if (!cancelled) setIsGenerating(false);
      }
    };

    run();
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tableName, columnName, isDesignMode, isEditMode, categoryValuesForNumbering, propRuleId]);

  // ─── 디바운스: manualInputValue 변경 시 suffix 동적 갱신 ────
  useEffect(() => {
    if (isDesignMode) return;
    if (!templateRef.current.includes("____")) return;
    if (!ruleIdRef.current) return;
    if (!userEditedRef.current) return;

    let cancelled = false;

    const timer = setTimeout(async () => {
      try {
        const resp = await previewNumberingCode(
          ruleIdRef.current!,
          formDataRef.current,
          manualInputValue || undefined,
        );
        if (cancelled) return;
        if (resp.success && resp.data?.generatedCode) {
          const newTemplate = resp.data.generatedCode;
          if (newTemplate.includes("____")) {
            templateRef.current = newTemplate;
            const parts = newTemplate.split("____");
            const prefix = parts[0] || "";
            const suffix = parts.length > 1 ? parts.slice(1).join("") : "";
            const combined = prefix + manualInputValue + suffix;
            setAutoGeneratedValue(combined);
            onChange(combined);
          }
        }
      } catch {
        /* 미리보기 실패 시 기존 suffix 유지 */
      }
    }, 300);

    return () => {
      cancelled = true;
      clearTimeout(timer);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [manualInputValue, isDesignMode]);

  // ─── beforeFormSave 리스너: 저장 직전 조합값 주입 ──────────
  useEffect(() => {
    if (isDesignMode || !columnName) return;

    const handler = (event: Event) => {
      const customEvent = event as CustomEvent;
      const template = templateRef.current;
      if (!template || !template.includes("____")) return;

      const parts = template.split("____");
      const prefix = parts[0] || "";
      const suffix = parts.length > 1 ? parts.slice(1).join("") : "";
      const combined = prefix + manualInputValue + suffix;

      if (customEvent.detail?.formData && columnName) {
        customEvent.detail.formData[columnName] = combined;
      }
    };

    window.addEventListener("beforeFormSave", handler);
    return () => window.removeEventListener("beforeFormSave", handler);
  }, [columnName, manualInputValue, isDesignMode]);

  // ─── 렌더 ──────────────────────────────────────────────────
  const displayValue =
    autoGeneratedValue !== null
      ? autoGeneratedValue
      : typeof value === "string"
        ? value
        : "";

  const template = templateRef.current;
  const canEdit = hadManualPartRef.current && template && !readonly && !disabled;

  // 박스 외관은 부모 (InputComponent) 가 담당. 여기선 슬롯 내부만.
  // 부모의 borderRadius 안에 prefix/suffix muted span 이 깨끗하게 잘리도록 overflow/inherit.
  const wrapperStyle: React.CSSProperties = {
    width: "100%",
    height: "100%",
    display: "flex",
    alignItems: "center",
    overflow: "hidden",
    borderRadius: "inherit",
    ...style,
  };

  // ____ 없는 경우: readonly 표시
  if (!canEdit) {
    return (
      <input
        type="text"
        value={displayValue}
        readOnly
        disabled={disabled || isGenerating}
        placeholder={isGenerating ? "생성 중..." : placeholder || "자동채번"}
        className={className}
        style={{
          width: "100%",
          height: "100%",
          padding: "5px 8px",
          fontSize: "13px",
          border: 0,
          borderRadius: 0,
          background: "hsl(var(--muted))",
          color: "hsl(var(--muted-foreground))",
          fontFamily: "monospace",
          outline: "none",
          boxSizing: "border-box",
          ...style,
        }}
      />
    );
  }

  // ____ 있는 경우: prefix + 편집 input + suffix
  const parts = template.split("____");
  const prefix = parts[0] || "";
  const suffix = parts.length > 1 ? parts.slice(1).join("") : "";

  return (
    <div className={className} style={wrapperStyle}>
      {prefix && (
        <span
          style={{
            display: "flex",
            alignItems: "center",
            height: "100%",
            padding: "0 8px",
            fontSize: "13px",
            fontFamily: "monospace",
            color: "hsl(var(--muted-foreground))",
            background: "hsl(var(--muted))",
            whiteSpace: "nowrap",
          }}
        >
          {prefix}
        </span>
      )}
      <input
        type="text"
        value={manualInputValue}
        onChange={(e) => {
          const newInput = e.target.value;
          setManualInputValue(newInput);
          userEditedRef.current = true;

          const newValue = prefix + newInput + suffix;
          setAutoGeneratedValue(newValue);
          onChange(newValue);

          // 외부 listener (다른 컴포넌트가 채번 변경 감지) 호환
          if (typeof window !== "undefined" && columnName) {
            window.dispatchEvent(
              new CustomEvent("numberingValueChanged", {
                detail: { columnName, value: newValue },
              }),
            );
          }
        }}
        placeholder="입력"
        disabled={disabled || isGenerating}
        style={{
          flex: 1,
          minWidth: 60,
          height: "100%",
          padding: "0 8px",
          fontSize: "13px",
          fontFamily: "monospace",
          border: 0,
          borderRadius: 0,
          background: "transparent",
          color: "hsl(var(--foreground))",
          outline: "none",
          boxSizing: "border-box",
        }}
      />
      {suffix && (
        <span
          style={{
            display: "flex",
            alignItems: "center",
            height: "100%",
            padding: "0 8px",
            fontSize: "13px",
            fontFamily: "monospace",
            color: "hsl(var(--muted-foreground))",
            background: "hsl(var(--muted))",
            whiteSpace: "nowrap",
          }}
        >
          {suffix}
        </span>
      )}
    </div>
  );
};
