"use client";

/**
 * CPExtras — cp 프리미티브 확장 헬퍼
 *
 * InvRepeaterConfigPanel 에서 검증된 패턴들을 다른 Inv*ConfigPanel 들이
 * 그대로 import 해서 재사용하기 위한 공용 컴포넌트 모음.
 *
 * - Hint / DimText / InlineLoader / SectionLabel — 작은 visual primitive
 * - CpChip / ChipPickerBox — 칩 형태 토글
 * - FeatureChipGrid / FeatureChipItem — 토글 묶음 chip grid
 *     · portal tooltip (부모 overflow 우회)
 *     · group cooldown (Stripe / Linear 패턴: 첫 호버 delay → group active 후 즉시 전환)
 * - CPVisualGrid / CPVisualOption — 시각 카드 grid (두께/색/사이즈/정렬 등 enum 시각 선택)
 *
 * 진실의 원천: notes/gbpark/2026-04-28-cp-panel-standard.md
 */

import React, { useState, useEffect, useRef, useCallback } from "react";
import { createPortal } from "react-dom";
import { Loader2 } from "lucide-react";

// ───────────────────────────────────────────────────────
// Hint — 보조 안내 텍스트 (3 tones)
// ───────────────────────────────────────────────────────
export function Hint({
  children,
  tone = "default",
}: {
  children: React.ReactNode;
  tone?: "default" | "warn" | "ok";
}) {
  const color =
    tone === "warn"
      ? "var(--v5-amber, #d97706)"
      : tone === "ok"
        ? "rgb(16, 185, 129)"
        : "var(--cp-text-muted)";
  return (
    <div style={{ fontSize: 10.5, color, marginTop: 4, lineHeight: 1.5 }}>{children}</div>
  );
}

// ───────────────────────────────────────────────────────
// DimText — read-only 텍스트 박스 (input 흉내)
// ───────────────────────────────────────────────────────
export function DimText({
  value,
  mono,
  muted,
}: {
  value: React.ReactNode;
  mono?: boolean;
  muted?: boolean;
}) {
  return (
    <div
      style={{
        height: 28,
        padding: "0 8px",
        display: "flex",
        alignItems: "center",
        fontSize: 12,
        fontFamily: mono ? "var(--v5-font-mono)" : "var(--v5-font-sans)",
        background: "var(--cp-bg-subtle)",
        border: "1px solid var(--cp-border)",
        borderRadius: 6,
        color: muted ? "var(--cp-text-muted)" : "var(--cp-text)",
      }}
    >
      {value}
    </div>
  );
}

// ───────────────────────────────────────────────────────
// InlineLoader — 작은 spinner + 텍스트
// ───────────────────────────────────────────────────────
export function InlineLoader({ text }: { text: string }) {
  return (
    <span
      style={{
        fontSize: 11,
        color: "var(--cp-text-muted)",
        display: "inline-flex",
        alignItems: "center",
        gap: 5,
      }}
    >
      <Loader2 size={11} className="animate-spin" /> {text}
    </span>
  );
}

// ───────────────────────────────────────────────────────
// SectionLabel — 섹션 내 작은 라벨 (icon + text)
// ───────────────────────────────────────────────────────
export function SectionLabel({
  icon,
  text,
  primary,
}: {
  icon?: React.ReactNode;
  text: string;
  primary?: boolean;
}) {
  return (
    <div
      style={{
        display: "inline-flex",
        alignItems: "center",
        gap: 5,
        marginBottom: 5,
        fontSize: 10.5,
        fontWeight: 600,
        color: primary ? "var(--v5-primary, #6c5ce7)" : "var(--cp-text-muted)",
      }}
    >
      {icon} {text}
    </div>
  );
}

// ───────────────────────────────────────────────────────
// CpChip — 활성/비활성 chip
// ───────────────────────────────────────────────────────
export function CpChip({
  active,
  onClick,
  children,
  tone = "default",
}: {
  active?: boolean;
  onClick?: () => void;
  children: React.ReactNode;
  tone?: "default" | "primary";
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      style={{
        display: "inline-flex",
        alignItems: "center",
        gap: 4,
        padding: "3px 8px",
        background: active
          ? "rgba(var(--v5-primary-rgb), 0.14)"
          : "var(--cp-bg-subtle)",
        border: `1px solid ${
          active ? "rgba(var(--v5-primary-rgb), 0.5)" : "var(--cp-border-subtle)"
        }`,
        borderRadius: 4,
        fontSize: 10.5,
        fontWeight: active ? 600 : 500,
        color: active
          ? "var(--v5-primary, #6c5ce7)"
          : tone === "primary"
            ? "var(--cp-text)"
            : "var(--cp-text-sec)",
        cursor: "pointer",
        fontFamily: "var(--v5-font-sans)",
      }}
    >
      {children}
    </button>
  );
}

// ───────────────────────────────────────────────────────
// ChipPickerBox — chip 그룹 컨테이너
// ───────────────────────────────────────────────────────
export function ChipPickerBox({ children }: { children: React.ReactNode }) {
  return (
    <div
      style={{
        display: "flex",
        flexWrap: "wrap",
        gap: 4,
        padding: 8,
        background: "var(--cp-bg-subtle)",
        border: "1px solid var(--cp-border-subtle)",
        borderRadius: 6,
      }}
    >
      {children}
    </div>
  );
}

// ───────────────────────────────────────────────────────
// FeatureChipGrid — 토글 묶음 chip grid + portal tooltip + group cooldown
// ───────────────────────────────────────────────────────
export interface FeatureChipItem {
  key: string;
  label: string;
  desc?: string;
  default?: boolean;
  isNew?: boolean;
}

const TIP_WIDTH = 280;
const TIP_PAD = 8;
const TIP_OPEN_DELAY = 500;
const TIP_CLOSE_GRACE = 250;
const TIP_GROUP_COOLDOWN = 500;

export function FeatureChipGrid({
  items,
  source,
  onToggle,
}: {
  items: FeatureChipItem[];
  source?: Record<string, any>;
  onToggle: (key: string, value: boolean) => void;
}) {
  const [hoverIdx, setHoverIdx] = useState<number | null>(null);
  const [chipRect, setChipRect] = useState<{ left: number; center: number; top: number } | null>(
    null,
  );
  const [tipVisible, setTipVisible] = useState(false);

  const groupActiveRef = useRef(false);
  const openTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const cooldownTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const clearTimer = (
    ref: React.MutableRefObject<ReturnType<typeof setTimeout> | null>,
  ) => {
    if (ref.current) {
      clearTimeout(ref.current);
      ref.current = null;
    }
  };

  const handleHoverEnter = useCallback((i: number, el: HTMLElement) => {
    clearTimer(closeTimerRef);
    clearTimer(cooldownTimerRef);

    const r = el.getBoundingClientRect();
    setHoverIdx(i);
    setChipRect({ left: r.left, center: r.left + r.width / 2, top: r.top });

    if (groupActiveRef.current) {
      setTipVisible(true);
    } else {
      clearTimer(openTimerRef);
      openTimerRef.current = setTimeout(() => {
        setTipVisible(true);
        groupActiveRef.current = true;
        openTimerRef.current = null;
      }, TIP_OPEN_DELAY);
    }
  }, []);

  const handleHoverLeave = useCallback(() => {
    clearTimer(openTimerRef);
    clearTimer(closeTimerRef);
    closeTimerRef.current = setTimeout(() => {
      setTipVisible(false);
      setHoverIdx(null);
      closeTimerRef.current = null;

      clearTimer(cooldownTimerRef);
      cooldownTimerRef.current = setTimeout(() => {
        groupActiveRef.current = false;
        cooldownTimerRef.current = null;
      }, TIP_GROUP_COOLDOWN);
    }, TIP_CLOSE_GRACE);
  }, []);

  useEffect(() => {
    return () => {
      clearTimer(openTimerRef);
      clearTimer(closeTimerRef);
      clearTimer(cooldownTimerRef);
    };
  }, []);

  const onCount = items.filter((it) => source?.[it.key] ?? it.default ?? false).length;

  const hoverItem = hoverIdx !== null ? items[hoverIdx] : null;
  const hoverActive = hoverItem ? !!(source?.[hoverItem.key] ?? hoverItem.default ?? false) : false;

  let tipLeft = 0;
  let arrowLeft = TIP_WIDTH / 2;
  if (chipRect && typeof window !== "undefined") {
    const rawLeft = chipRect.center - TIP_WIDTH / 2;
    const minLeft = TIP_PAD;
    const maxLeft = window.innerWidth - TIP_WIDTH - TIP_PAD;
    tipLeft = Math.min(Math.max(rawLeft, minLeft), maxLeft);
    arrowLeft = chipRect.center - tipLeft;
    arrowLeft = Math.min(Math.max(arrowLeft, 12), TIP_WIDTH - 12);
  }

  return (
    <div>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 6,
          marginBottom: 5,
          fontSize: 10,
          color: "var(--cp-text-muted)",
          fontFamily: "var(--v5-font-mono)",
          letterSpacing: 0.02,
        }}
      >
        <span>활성</span>
        <span style={{ color: "var(--v5-primary, #6c5ce7)", fontWeight: 700 }}>{onCount}</span>
        <span>/ {items.length}</span>
      </div>
      <div
        style={{
          display: "grid",
          gridTemplateColumns: "repeat(auto-fill, minmax(96px, 1fr))",
          gap: 5,
        }}
      >
        {items.map((it, i) => {
          const active = !!(source?.[it.key] ?? it.default ?? false);
          return (
            <button
              key={it.key}
              type="button"
              onClick={() => onToggle(it.key, !active)}
              onFocus={(e) => handleHoverEnter(i, e.currentTarget)}
              onBlur={handleHoverLeave}
              onMouseEnter={(e) => {
                handleHoverEnter(i, e.currentTarget as HTMLElement);
                if (!active) {
                  (e.currentTarget as HTMLButtonElement).style.background =
                    "var(--cp-surface-hover, var(--cp-surface))";
                }
              }}
              onMouseLeave={(e) => {
                handleHoverLeave();
                if (!active) {
                  (e.currentTarget as HTMLButtonElement).style.background =
                    "var(--cp-bg-subtle)";
                }
              }}
              style={{
                position: "relative",
                display: "flex",
                alignItems: "center",
                gap: 6,
                padding: "6px 8px 6px 7px",
                background: active
                  ? "rgba(var(--v5-primary-rgb), 0.10)"
                  : "var(--cp-bg-subtle)",
                border: `1px solid ${
                  active ? "rgba(var(--v5-primary-rgb), 0.45)" : "var(--cp-border-subtle)"
                }`,
                borderRadius: 5,
                cursor: "pointer",
                fontFamily: "var(--v5-font-sans)",
                boxShadow: active
                  ? "0 0 0 2px rgba(var(--v5-primary-rgb), 0.06), 0 1px 2px rgba(0,0,0,0.03)"
                  : "none",
                transition: "all .14s ease",
                textAlign: "left",
                minHeight: 26,
              }}
            >
              <span
                aria-hidden
                style={{
                  width: 6,
                  height: 6,
                  borderRadius: 999,
                  background: active
                    ? "var(--v5-primary, #6c5ce7)"
                    : "var(--cp-border-strong, var(--cp-border))",
                  boxShadow: active ? "0 0 5px rgba(var(--v5-primary-rgb), 0.55)" : "none",
                  flexShrink: 0,
                  transition: "all .14s ease",
                }}
              />
              <span
                style={{
                  flex: 1,
                  fontSize: 11,
                  fontWeight: active ? 600 : 500,
                  color: active ? "var(--cp-text)" : "var(--cp-text-sec)",
                  overflow: "hidden",
                  textOverflow: "ellipsis",
                  whiteSpace: "nowrap",
                  letterSpacing: "-0.005em",
                }}
              >
                {it.label}
              </span>
              {it.isNew && (
                <span
                  style={{
                    fontSize: 8.5,
                    fontWeight: 700,
                    padding: "1px 4px",
                    background: "rgba(var(--v5-primary-rgb), 0.15)",
                    color: "var(--v5-primary, #6c5ce7)",
                    borderRadius: 3,
                    letterSpacing: "0.04em",
                  }}
                >
                  NEW
                </span>
              )}
            </button>
          );
        })}
      </div>

      {tipVisible &&
        hoverItem &&
        hoverItem.desc &&
        chipRect &&
        typeof document !== "undefined" &&
        createPortal(
          <div
            role="tooltip"
            style={{
              position: "fixed",
              top: chipRect.top - 8,
              left: tipLeft,
              transform: "translateY(-100%)",
              width: TIP_WIDTH,
              pointerEvents: "none",
              zIndex: 9999,
            }}
          >
            <div
              style={{
                position: "relative",
                background: "rgba(20, 18, 36, 0.97)",
                color: "#fff",
                padding: "8px 11px 7px 10px",
                borderRadius: 6,
                boxShadow:
                  "0 12px 32px rgba(0,0,0,0.42), 0 0 0 1px rgba(var(--v5-primary-rgb), 0.3)",
                fontFamily: "var(--v5-font-sans)",
                animation: "cp-fade-up 0.14s ease-out",
                lineHeight: 1.45,
              }}
            >
              <div
                style={{
                  display: "flex",
                  alignItems: "center",
                  gap: 5,
                  marginBottom: 3,
                }}
              >
                <span
                  aria-hidden
                  style={{
                    width: 5,
                    height: 5,
                    borderRadius: 999,
                    background: hoverActive ? "#10b981" : "rgba(255,255,255,0.32)",
                    boxShadow: hoverActive ? "0 0 5px rgba(16,185,129,0.7)" : "none",
                    flexShrink: 0,
                  }}
                />
                <span
                  style={{
                    fontSize: 11.5,
                    fontWeight: 700,
                    color: "#fff",
                    letterSpacing: "-0.01em",
                    flex: 1,
                    whiteSpace: "nowrap",
                  }}
                >
                  {hoverItem.label}
                </span>
                {hoverItem.isNew && (
                  <span
                    style={{
                      fontSize: 8,
                      fontWeight: 700,
                      padding: "1px 4px",
                      background: "rgba(var(--v5-primary-rgb), 0.3)",
                      color: "#b8b3ff",
                      borderRadius: 3,
                      letterSpacing: "0.04em",
                      marginLeft: 2,
                    }}
                  >
                    NEW
                  </span>
                )}
              </div>
              <div
                style={{
                  fontSize: 10.5,
                  color: "rgba(255,255,255,0.82)",
                  fontWeight: 400,
                  whiteSpace: "pre-line",
                  lineHeight: 1.55,
                }}
              >
                {hoverItem.desc}
              </div>
              <div
                style={{
                  marginTop: 5,
                  paddingTop: 4,
                  borderTop: "1px solid rgba(255,255,255,0.1)",
                  fontSize: 9.5,
                  color: "rgba(255,255,255,0.45)",
                  fontFamily: "var(--v5-font-mono)",
                  letterSpacing: 0.02,
                  display: "flex",
                  alignItems: "center",
                  gap: 5,
                }}
              >
                <span style={{ color: hoverActive ? "#10b981" : "rgba(255,255,255,0.42)" }}>
                  {hoverActive ? "● ON" : "○ OFF"}
                </span>
                <span style={{ opacity: 0.4 }}>·</span>
                <span>{hoverItem.key}</span>
              </div>
              <span
                aria-hidden
                style={{
                  position: "absolute",
                  top: "100%",
                  left: arrowLeft,
                  transform: "translateX(-50%)",
                  width: 0,
                  height: 0,
                  borderLeft: "5px solid transparent",
                  borderRight: "5px solid transparent",
                  borderTop: "5px solid rgba(20, 18, 36, 0.97)",
                }}
              />
            </div>
          </div>,
          document.body,
        )}
    </div>
  );
}

// ───────────────────────────────────────────────────────
// CPVisualGrid — 시각 카드 grid (두께/색/사이즈/정렬 등 enum 시각 선택)
//
// option 의 preview 가 시각 미리보기 (ReactNode). 라벨은 카드 하단 작은 글씨.
// FeatureChipGrid 와 다른 점:
//   - 단일 선택 (radio 같음)
//   - preview 가 옵션마다 다른 시각 (미리보기 중요한 enum)
//   - 옵션 수 적음 (3~6 권장)
// ───────────────────────────────────────────────────────
export interface CPVisualOption {
  value: string;
  label: string;
  preview?: React.ReactNode;
  desc?: string;
}

export function CPVisualGrid({
  options,
  value,
  onChange,
  cols = 3,
  cardHeight = 56,
}: {
  options: CPVisualOption[];
  value?: string;
  onChange: (v: string) => void;
  cols?: number;
  cardHeight?: number;
}) {
  return (
    <div
      style={{
        display: "grid",
        gridTemplateColumns: `repeat(${cols}, 1fr)`,
        gap: 6,
      }}
    >
      {options.map((opt) => {
        const active = value === opt.value;
        return (
          <button
            key={opt.value}
            type="button"
            onClick={() => onChange(opt.value)}
            title={opt.desc || opt.label}
            style={{
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
              justifyContent: "center",
              gap: 4,
              minHeight: cardHeight,
              padding: "7px 6px",
              background: active
                ? "rgba(var(--v5-primary-rgb), 0.10)"
                : "var(--cp-bg-subtle)",
              border: `1px solid ${
                active ? "rgba(var(--v5-primary-rgb), 0.5)" : "var(--cp-border-subtle)"
              }`,
              borderRadius: 6,
              cursor: "pointer",
              fontFamily: "var(--v5-font-sans)",
              boxShadow: active
                ? "0 0 0 2px rgba(var(--v5-primary-rgb), 0.07)"
                : "none",
              transition: "all .14s ease",
              color: "var(--cp-text)",
            }}
            onMouseEnter={(e) => {
              if (!active) {
                (e.currentTarget as HTMLButtonElement).style.background =
                  "var(--cp-surface-hover, var(--cp-surface))";
              }
            }}
            onMouseLeave={(e) => {
              if (!active) {
                (e.currentTarget as HTMLButtonElement).style.background =
                  "var(--cp-bg-subtle)";
              }
            }}
          >
            {opt.preview && (
              <div
                style={{
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  width: "100%",
                  flex: 1,
                  color: active ? "var(--v5-primary, #6c5ce7)" : "var(--cp-text-sec)",
                }}
              >
                {opt.preview}
              </div>
            )}
            <span
              style={{
                fontSize: 10,
                fontWeight: active ? 600 : 500,
                color: active ? "var(--cp-text)" : "var(--cp-text-muted)",
                letterSpacing: "-0.005em",
              }}
            >
              {opt.label}
            </span>
          </button>
        );
      })}
    </div>
  );
}
