/**
 * 보조지표 설정 — 색상 + 투명도 (스와치 클릭 시 팔레트·고급 선택기)
 */
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { createPortal } from 'react-dom';
import { parsePlotColor, formatPlotColor, plotColorCss } from '../utils/plotColorUtils';
import { getOpacityPercentSpec } from '../utils/indicatorParamSpec';
import NumericParamInput from './NumericParamInput';
import ColorPickerPanel from './ColorPickerPanel';

export interface ColorInputProps {
  value: string;
  onChange: (v: string) => void;
  disabled?: boolean;
  /** false — 인라인 네이티브 color input 숨김(설정 화면: OS 피커만 뜨는 문제 방지) */
  showCompactNative?: boolean;
  /** false — 바깥 클릭으로 닫지 않음(확인·✕·Esc 로만 닫기) */
  closeOnClickOutside?: boolean;
}

const ColorInput: React.FC<ColorInputProps> = ({
  value,
  onChange,
  disabled = false,
  showCompactNative = true,
  closeOnClickOutside = false,
}) => {
  const { hex6, alpha } = parsePlotColor(value);
  const [open, setOpen] = useState(false);
  const anchorRef = useRef<HTMLDivElement>(null);
  const popoverRef = useRef<HTMLDivElement>(null);
  const [pos, setPos] = useState({ top: 0, left: 0 });

  const updatePosition = useCallback(() => {
    const el = anchorRef.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const popW = 280;
    let left = rect.left;
    if (left + popW > window.innerWidth - 12) {
      left = window.innerWidth - popW - 12;
    }
    setPos({ top: rect.bottom + 6, left: Math.max(8, left) });
  }, []);

  useEffect(() => {
    if (!open) return;
    updatePosition();
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setOpen(false);
    };
    const onScroll = () => updatePosition();
    window.addEventListener('keydown', onKey);
    window.addEventListener('resize', updatePosition);
    window.addEventListener('scroll', onScroll, true);
    return () => {
      window.removeEventListener('keydown', onKey);
      window.removeEventListener('resize', updatePosition);
      window.removeEventListener('scroll', onScroll, true);
    };
  }, [open, updatePosition]);

  useEffect(() => {
    if (!open || !closeOnClickOutside) return;
    const onDocPointer = (e: Event) => {
      const t = e.target as Node;
      if (anchorRef.current?.contains(t) || popoverRef.current?.contains(t)) return;
      setOpen(false);
    };
    document.addEventListener('mousedown', onDocPointer, true);
    document.addEventListener('pointerdown', onDocPointer, true);
    return () => {
      document.removeEventListener('mousedown', onDocPointer, true);
      document.removeEventListener('pointerdown', onDocPointer, true);
    };
  }, [open, closeOnClickOutside]);

  const patchHex = (h: string) => onChange(formatPlotColor(h, alpha));
  const patchAlpha = (a: number) => onChange(formatPlotColor(hex6, a));

  const closePopover = useCallback(() => setOpen(false), []);

  const popover = open && typeof document !== 'undefined' ? (
    <div
      ref={popoverRef}
      className="ism-color-popover"
      style={{ top: pos.top, left: pos.left }}
      role="dialog"
      aria-label="색상 선택"
      onMouseDown={e => e.stopPropagation()}
      onPointerDown={e => e.stopPropagation()}
    >
      <div className="ism-color-popover-header">
        <span className="ism-color-popover-title">색상 선택</span>
        <button
          type="button"
          className="gc-popup-close ism-color-popover-close"
          onClick={closePopover}
          aria-label="색상 선택 닫기"
        >
          ✕
        </button>
      </div>
      {showCompactNative && (
        <div className="ism-color-popover-native">
          <label className="ism-color-native-label">
            <span className="ism-style-label">직접 선택</span>
            <input
              type="color"
              className="ism-color-picker"
              value={hex6}
              onChange={e => patchHex(e.target.value)}
            />
          </label>
        </div>
      )}
      <ColorPickerPanel hex6={hex6} onHexChange={patchHex} />
      <div className="ism-color-popover-footer">
        <button type="button" className="plsp-popup-ok" onClick={closePopover}>
          확인
        </button>
      </div>
    </div>
  ) : null;

  return (
    <div className={`ism-color-wrap${disabled ? ' ism-color-wrap--disabled' : ''}`} ref={anchorRef}>
      <button
        type="button"
        className="ism-color-swatch-btn"
        title="색상 선택"
        aria-expanded={open}
        disabled={disabled}
        onClick={() => {
          if (disabled) return;
          setOpen(v => !v);
          if (!open) requestAnimationFrame(updatePosition);
        }}
      >
        <span className="ism-color-swatch-preview" style={{ background: plotColorCss(value) }} />
      </button>
      {showCompactNative && (
        <input
          type="color"
          className="ism-color-picker ism-color-picker--compact"
          value={hex6}
          title="브라우저 색상 선택"
          disabled={disabled}
          onChange={e => patchHex(e.target.value)}
        />
      )}
      <NumericParamInput
        className="ism-input ism-alpha-input"
        value={alpha}
        spec={getOpacityPercentSpec(alpha)}
        disabled={disabled}
        onChange={patchAlpha}
      />
      <span className="ism-alpha-label">%</span>
      {popover ? createPortal(popover, document.body) : null}
    </div>
  );
};

export default ColorInput;
