/**
 * 그리드형 n×n 레이아웃 선택 (TradingView 스타일 팝업) — 알림 목록·가상매매 공용
 */
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import {
  gridPresetsByGroup,
  getTradeNotificationGridPreset,
  type TradeNotificationGridPreset,
  type TradeNotificationGridPresetId,
} from '../../utils/tradeNotificationGridPresets';

export type GridLayoutPickerVariant = 'tnl' | 'vtd';

interface Props {
  value: TradeNotificationGridPresetId;
  onChange: (id: TradeNotificationGridPresetId) => void;
  disabled?: boolean;
  /** CSS 클래스 접두사 — tnl(알림목록) | vtd(가상매매) */
  variant?: GridLayoutPickerVariant;
  /** 팝업 정렬 (헤더 좌측 배치 시 left) */
  popoverAlign?: 'left' | 'right';
}

function cls(variant: GridLayoutPickerVariant, suffix: string): string {
  return `${variant}-grid-layout-${suffix}`;
}

/** 20×20 와이어프레임 아이콘 */
const LayoutIcon: React.FC<{ preset: TradeNotificationGridPreset }> = ({ preset }) => {
  const s = 20;
  const g = 1;
  const cells: Array<{ x: number; y: number; w: number; h: number }> = [];

  switch (preset.id) {
    case '1x1':
      cells.push({ x: 0, y: 0, w: s, h: s });
      break;
    case '2x1':
      cells.push({ x: 0, y: 0, w: 9, h: s }, { x: 10, y: 0, w: 9, h: s });
      break;
    case '1x2':
      cells.push({ x: 0, y: 0, w: s, h: 9 }, { x: 0, y: 10, w: s, h: 9 });
      break;
    case '3x1':
      cells.push(
        { x: 0, y: 0, w: 6, h: s },
        { x: 7, y: 0, w: 6, h: s },
        { x: 14, y: 0, w: 6, h: s },
      );
      break;
    case '1x3':
      cells.push(
        { x: 0, y: 0, w: s, h: 6 },
        { x: 0, y: 7, w: s, h: 6 },
        { x: 0, y: 14, w: s, h: 6 },
      );
      break;
    case '2x1-31':
      cells.push({ x: 0, y: 0, w: 9, h: s }, { x: 10, y: 0, w: 9, h: 9 }, { x: 10, y: 10, w: 9, h: 9 });
      break;
    case '2x2':
      cells.push(
        { x: 0, y: 0, w: 9, h: 9 },
        { x: 10, y: 0, w: 9, h: 9 },
        { x: 0, y: 10, w: 9, h: 9 },
        { x: 10, y: 10, w: 9, h: 9 },
      );
      break;
    case '4x1':
      for (let i = 0; i < 4; i++) cells.push({ x: i * 5, y: 0, w: 4, h: s });
      break;
    case '1x4':
      for (let i = 0; i < 4; i++) cells.push({ x: 0, y: i * 5, w: s, h: 4 });
      break;
    case '2x1-211':
      cells.push(
        { x: 0, y: 0, w: 9, h: 9 },
        { x: 10, y: 0, w: 9, h: 9 },
        { x: 0, y: 10, w: 9, h: 9 },
        { x: 10, y: 10, w: 9, h: 9 },
      );
      break;
    case '5x1':
      for (let i = 0; i < 5; i++) cells.push({ x: i * 4, y: 0, w: 3, h: s });
      break;
    case '3x2':
      for (let c = 0; c < 3; c++) {
        for (let r = 0; r < 2; r++) {
          cells.push({ x: c * 7, y: r * 10, w: 6, h: 9 });
        }
      }
      break;
    case '2x3':
      for (let c = 0; c < 2; c++) {
        for (let r = 0; r < 3; r++) {
          cells.push({ x: c * 10, y: r * 7, w: 9, h: 6 });
        }
      }
      break;
    case '4x2':
      for (let c = 0; c < 4; c++) {
        for (let r = 0; r < 2; r++) {
          cells.push({ x: c * 5, y: r * 10, w: 4, h: 9 });
        }
      }
      break;
    case '2x4':
      for (let c = 0; c < 2; c++) {
        for (let r = 0; r < 4; r++) {
          cells.push({ x: c * 10, y: r * 5, w: 9, h: 4 });
        }
      }
      break;
    default:
      cells.push({ x: 0, y: 0, w: s, h: s });
  }

  return (
    <svg width="22" height="22" viewBox="0 0 20 20" aria-hidden className="grid-preset-icon-svg">
      {cells.map((c, i) => (
        <rect
          key={i}
          x={c.x}
          y={c.y}
          width={c.w}
          height={c.h}
          rx={0.5}
          fill="none"
          stroke="currentColor"
          strokeWidth={g}
        />
      ))}
    </svg>
  );
};

const POPOVER_WIDTH = 320;

const GridLayoutPicker: React.FC<Props> = ({
  value,
  onChange,
  disabled = false,
  variant = 'tnl',
  popoverAlign = 'right',
}) => {
  const [open, setOpen] = useState(false);
  const [popoverPos, setPopoverPos] = useState<{ top: number; left: number } | null>(null);
  const rootRef = useRef<HTMLDivElement>(null);
  const popoverRef = useRef<HTMLDivElement>(null);
  const active = getTradeNotificationGridPreset(value);
  const groups = [...gridPresetsByGroup().entries()].sort((a, b) => a[0] - b[0]);

  const updatePopoverPos = useCallback(() => {
    const el = rootRef.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const width = Math.min(POPOVER_WIDTH, window.innerWidth - 48);
    const left = popoverAlign === 'left'
      ? rect.left
      : rect.right - width;
    setPopoverPos({
      top: rect.bottom + 8,
      left: Math.max(8, Math.min(left, window.innerWidth - width - 8)),
    });
  }, [popoverAlign]);

  useEffect(() => {
    if (!open) {
      setPopoverPos(null);
      return;
    }
    updatePopoverPos();
    window.addEventListener('resize', updatePopoverPos);
    window.addEventListener('scroll', updatePopoverPos, true);
    return () => {
      window.removeEventListener('resize', updatePopoverPos);
      window.removeEventListener('scroll', updatePopoverPos, true);
    };
  }, [open, updatePopoverPos]);

  useEffect(() => {
    if (!open) return;
    const onDoc = (e: MouseEvent) => {
      const t = e.target as Node;
      if (rootRef.current?.contains(t) || popoverRef.current?.contains(t)) return;
      setOpen(false);
    };
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setOpen(false);
    };
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return () => {
      document.removeEventListener('mousedown', onDoc);
      document.removeEventListener('keydown', onKey);
    };
  }, [open]);

  const popoverClass = [
    cls(variant, 'popover'),
    cls(variant, 'popover--portal'),
    popoverAlign === 'left' ? cls(variant, 'popover--align-left') : '',
  ].filter(Boolean).join(' ');

  const popover = open && popoverPos ? (
    <div
      ref={popoverRef}
      className={popoverClass}
      role="dialog"
      aria-label="그리드 배치"
      style={{
        position: 'fixed',
        top: popoverPos.top,
        left: popoverPos.left,
        right: 'auto',
        zIndex: 10000,
        width: Math.min(POPOVER_WIDTH, window.innerWidth - 48),
      }}
    >
      <p className={cls(variant, 'popover-title')}>그리드 배치</p>
      {groups.map(([group, presets]) => (
        <div key={group} className={cls(variant, 'group')}>
          <span className={cls(variant, 'group-lbl')}>{group}</span>
          <div className={cls(variant, 'group-row')}>
            {presets.map(preset => (
              <button
                key={preset.id}
                type="button"
                className={[
                  `${variant}-grid-preset-btn`,
                  value === preset.id ? `${variant}-grid-preset-btn--on` : '',
                ].filter(Boolean).join(' ')}
                title={`${preset.label} (${preset.cols}열)`}
                aria-label={`${preset.label} 배치`}
                aria-pressed={value === preset.id}
                onClick={() => {
                  onChange(preset.id);
                  setOpen(false);
                }}
              >
                <LayoutIcon preset={preset} />
              </button>
            ))}
          </div>
        </div>
      ))}
    </div>
  ) : null;

  return (
    <div className={cls(variant, 'picker')} ref={rootRef}>
      <button
        type="button"
        className={[
          cls(variant, 'trigger'),
          open ? cls(variant, 'trigger--open') : '',
          disabled ? cls(variant, 'trigger--disabled') : '',
        ].filter(Boolean).join(' ')}
        title={`그리드 배치: ${active.label}`}
        aria-label="그리드 배치 선택"
        aria-expanded={open}
        aria-haspopup="dialog"
        disabled={disabled}
        onClick={() => !disabled && setOpen(o => !o)}
      >
        <LayoutIcon preset={active} />
      </button>

      {popover && createPortal(popover, document.body)}
    </div>
  );
};

export default GridLayoutPicker;
