'use client';

import { useState, useEffect, useRef, useMemo } from 'react';
import { CTRL_NODE_TYPES, useControlMode } from './hooks/useControlMode';

/**
 * 노드 설정 팝오버 — Phase 2: schema-driven dropdown
 *
 * 핵심: 노드와 연결된 테이블의 컬럼/enum 메타를 dropdown 으로 자동 매핑.
 *   - 영어 자유 입력 폐기 (실사용 불가)
 *   - 한글 라벨 우선 + 영문 컬럼 sub
 *   - enum 컬럼이면 값도 dropdown
 *   - multi-table 시 optgroup 으로 namespace 구분
 *   - 저장은 fully qualified { table, column } 객체 (Phase 3 준비)
 */
export function NodeConfigPopover() {
  const { configNodeId, ruleNodes, ruleConnections, setConfigNodeId, updateRuleNode } = useControlMode();
  const popRef = useRef<HTMLDivElement>(null);
  const [open, setOpen] = useState(false);

  const node = configNodeId ? ruleNodes.find((n) => n.id === configNodeId) : null;
  const def = node ? CTRL_NODE_TYPES[node.type] : null;

  // 현재 노드와 연결된 테이블 노드들 (양방향 — from/to 어느 쪽이든)
  const connectedTables = useMemo<Record<string, any>[]>(() => {
    if (!configNodeId) return [];
    const tableNodeIds = new Set<string>();
    ruleConnections.forEach((c) => {
      if (c.from_node_id === configNodeId) tableNodeIds.add(c.to_node_id);
      if (c.to_node_id === configNodeId) tableNodeIds.add(c.from_node_id);
    });
    return ruleNodes.filter((n) => n.type === 'table' && tableNodeIds.has(n.id));
  }, [configNodeId, ruleNodes, ruleConnections]);

  useEffect(() => {
    if (configNodeId && node) {
      requestAnimationFrame(() => setOpen(true));
    } else {
      setOpen(false);
    }
  }, [configNodeId, node]);

  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (!configNodeId) return;
      const t = e.target as HTMLElement;
      if (t.closest('.ctrl-cfg-pop')) return;
      if (t.closest('.v3-rule-node')) return;
      if (t.closest('.tbl-node')) return;
      if (t.closest('.ctrl-an-body')) return;
      setConfigNodeId(null);
    };
    document.addEventListener('click', handler);
    return () => document.removeEventListener('click', handler);
  }, [configNodeId, setConfigNodeId]);

  if (!node || !def) return null;

  const handleSave = (summary: string, config: Record<string, any>) => {
    updateRuleNode(node.id, { config: { ...node.config, ...config, summary } });
    setConfigNodeId(null);
  };

  return (
    <div
      ref={popRef}
      className={`ctrl-cfg-pop${open ? ' open' : ''}`}
      style={{ left: node.x + 172, top: node.y }}
    >
      <div className="cfg-hd">{def.icon} {def.label} 설정</div>
      <ConfigForm
        type={node.type}
        config={node.config ?? {}}
        connectedTables={connectedTables}
        onSave={handleSave}
        onClose={() => setConfigNodeId(null)}
      />
    </div>
  );
}

/* ─── Helpers ─── */

interface ColumnMeta {
  tableName: string;
  tableLabel: string;
  column: string;
  label: string;
  type: string;
  options?: Array<{ value: string; label: string }>;
  pk?: boolean;
}

/** 연결된 테이블들의 모든 컬럼을 flat 으로 + 표시 정보 포함 */
function flattenColumns(tables: Record<string, any>[]): ColumnMeta[] {
  const out: ColumnMeta[] = [];
  tables.forEach((t) => {
    const tName = t.table_name ?? t.tableName ?? '';
    const tLabel = t.label ?? tName;
    (t.columns ?? []).forEach((c: Record<string, any>) => {
      const colName = c.column ?? c.name ?? c.COLUMN_NAME ?? '';
      if (!colName) return;
      out.push({
        tableName: tName,
        tableLabel: tLabel,
        column: colName,
        label: c.label ?? c.dname ?? colName,
        type: c.type ?? c.dtype ?? 'text',
        options: c.options,
        pk: !!c.pk,
      });
    });
  });
  return out;
}

/** fully qualified id ↔ 객체 변환 */
function serializeField(field: any): string {
  if (!field) return '';
  if (typeof field === 'string') return field;  // legacy
  if (field.table && field.column) return `${field.table}|${field.column}`;
  return '';
}
function deserializeField(s: string): { table: string; column: string } | null {
  if (!s || !s.includes('|')) return null;
  const [table, column] = s.split('|');
  return { table, column };
}

/** field value (string or {table,column}) 으로 ColumnMeta 찾기 */
function findColumn(cols: ColumnMeta[], field: any): ColumnMeta | null {
  if (!field) return null;
  if (typeof field === 'string') return cols.find((c) => c.column === field) ?? null;
  if (field.table && field.column) {
    return cols.find((c) => c.tableName === field.table && c.column === field.column) ?? null;
  }
  return null;
}

/** 한글 라벨 표시 (field) */
function displayField(field: any, cols: ColumnMeta[]): string {
  const col = findColumn(cols, field);
  if (col) return col.label;
  if (typeof field === 'string') return field;
  if (field?.column) return field.column;
  return '?';
}

/* ─── Reusable pickers ─── */

function FieldPicker({
  tables, value, onChange, placeholder,
}: {
  tables: Record<string, any>[];
  value: any;
  onChange: (field: { table: string; column: string }) => void;
  placeholder?: string;
}) {
  const cols = useMemo(() => flattenColumns(tables), [tables]);
  if (tables.length === 0) {
    return <div className="cfg-empty">연결된 테이블 없음 — 먼저 테이블 카드를 노드에 연결</div>;
  }
  const currentId = serializeField(value);

  return (
    <select
      className="cfg-sel"
      value={currentId}
      onChange={(e) => {
        const f = deserializeField(e.target.value);
        if (f) onChange(f);
      }}
    >
      <option value="">{placeholder ?? '컬럼 선택...'}</option>
      {tables.map((tbl) => {
        const tName = tbl.table_name ?? tbl.tableName ?? '';
        const tLabel = tbl.label ?? tName;
        const tableCols = cols.filter((c) => c.tableName === tName);
        if (tableCols.length === 0) return null;
        const groupLabel = tLabel !== tName ? `${tLabel} · ${tName}` : tName;
        return (
          <optgroup key={tName} label={groupLabel}>
            {tableCols.map((c) => {
              const id = `${c.tableName}|${c.column}`;
              const dispLabel = c.label !== c.column ? `${c.label} (${c.column})` : c.column;
              return (
                <option key={id} value={id}>
                  {dispLabel}{c.pk ? ' · PK' : ''}{c.type === 'select' ? ' · enum' : ''}
                </option>
              );
            })}
          </optgroup>
        );
      })}
    </select>
  );
}

function TablePicker({
  tables, value, onChange, placeholder,
}: {
  tables: Record<string, any>[];
  value: any;
  onChange: (tableName: string) => void;
  placeholder?: string;
}) {
  // 자동 채움 — Strict 모드 안전 useEffect (committed lifecycle 에서만 실행)
  const single = tables.length === 1
    ? (tables[0].table_name ?? tables[0].tableName ?? '')
    : null;
  useEffect(() => {
    if (single && value !== single) onChange(single);
  }, [single, value, onChange]);

  if (tables.length === 0) {
    return <div className="cfg-empty">연결된 테이블 없음 — 먼저 테이블 카드를 노드에 연결</div>;
  }
  // 1개면 자동 readonly
  if (tables.length === 1) {
    const t = tables[0];
    const tName = t.table_name ?? t.tableName ?? '';
    const tLabel = t.label ?? tName;
    return (
      <div className="cfg-static">
        <span className="cfg-static-main">{tLabel}</span>
        {tLabel !== tName && <span className="cfg-static-sub">{tName}</span>}
        <span className="cfg-static-hint">(자동)</span>
      </div>
    );
  }
  // 2개+ 면 dropdown
  const current = typeof value === 'string' ? value : (value?.table ?? '');
  return (
    <select className="cfg-sel" value={current} onChange={(e) => onChange(e.target.value)}>
      <option value="">{placeholder ?? '테이블 선택...'}</option>
      {tables.map((t) => {
        const tName = t.table_name ?? t.tableName ?? '';
        const tLabel = t.label ?? tName;
        return (
          <option key={tName} value={tName}>
            {tLabel}{tLabel !== tName ? ` (${tName})` : ''}
          </option>
        );
      })}
    </select>
  );
}

function ValuePicker({
  tables, fieldRef, value, onChange, placeholder,
}: {
  tables: Record<string, any>[];
  fieldRef: any;  // 어느 컬럼의 값인지
  value: any;
  onChange: (v: string) => void;
  placeholder?: string;
}) {
  const cols = useMemo(() => flattenColumns(tables), [tables]);
  const col = findColumn(cols, fieldRef);

  // enum 컬럼이면 dropdown
  if (col?.type === 'select' && col.options && col.options.length > 0) {
    return (
      <select className="cfg-sel" value={value ?? ''} onChange={(e) => onChange(e.target.value)}>
        <option value="">{placeholder ?? '값 선택...'}</option>
        {col.options.map((opt) => (
          <option key={opt.value} value={opt.value}>
            {opt.label}{opt.label !== opt.value ? ` (${opt.value})` : ''}
          </option>
        ))}
      </select>
    );
  }
  // 기본 typed input
  return (
    <input
      className="cfg-inp"
      value={value ?? ''}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder ?? (col ? `${col.label} 값` : '값 입력')}
    />
  );
}

/* ─── ConfigForm ─── */

function ConfigForm({
  type, config, connectedTables, onSave, onClose,
}: {
  type: string;
  config: Record<string, any>;
  connectedTables: Record<string, any>[];
  onSave: (summary: string, config: Record<string, any>) => void;
  onClose: () => void;
}) {
  const [vals, setVals] = useState<Record<string, any>>(config);
  const set = (k: string, v: any) => setVals((p) => ({ ...p, [k]: v }));
  const cols = useMemo(() => flattenColumns(connectedTables), [connectedTables]);

  const handleSave = () => {
    let summary = '';
    const fLabel = (f: any) => displayField(f, cols);
    const tLabel = (tName: string) => {
      const t = connectedTables.find((x) => (x.table_name ?? x.tableName) === tName);
      return t?.label ?? tName ?? '?';
    };
    switch (type) {
      case 'condition':
        summary = `${fLabel(vals.field)} ${vals.op || '='} "${vals.value || '?'}"`;
        break;
      case 'status-change':
        summary = `${tLabel(vals.table)}.${fLabel(vals.field)} → "${vals.value || '?'}"`;
        break;
      case 'auto-insert':
        summary = `→ ${tLabel(vals.table)} INSERT`;
        break;
      case 'timer':
        summary = `${fLabel(vals.field)} +${vals.amount || 0}${vals.unit || '일'} 경과`;
        break;
      case 'notification':
        summary = `${vals.channel || '이메일'} → ${vals.target || '담당자'}`;
        break;
      case 'approval':
        summary = `${vals.approver || '팀장'} 승인${vals.condition ? ` (${vals.condition})` : ''}`;
        break;
      case 'calculation':
        summary = `${tLabel(vals.table)}.${fLabel(vals.field)} = ${vals.formula || '?'}`;
        break;
      case 'webhook':
        summary = `${vals.method || 'POST'} ${(vals.url || '').slice(0, 25)}...`;
        break;
      case 'validation':
        summary = `${fLabel(vals.field)} ${vals.rule || '필수값'}`;
        break;
      case 'log':
        summary = `로그: ${vals.content || '?'}`;
        break;
      case 'delete':
        summary = `${tLabel(vals.table)} ${vals.mode === 'soft' ? 'soft delete' : 'hard delete'}`;
        break;
      case 'document':
        summary = `${vals.template || '?'} → ${vals.format || 'pdf'}`;
        break;
      case 'delay':
        summary = `${vals.amount || 0}${vals.unit || '분'} 대기`;
        break;
      case 'loop':
        summary = vals.iterField ? `for each ${vals.iterField}` : `${vals.count || 1}회 반복`;
        break;
      case 'parallel':
        summary = `${vals.branches || 2}개 병렬 실행`;
        break;
      case 'merge':
        summary = vals.strategy === 'all' ? '모든 분기 대기 (all)' : '먼저 도착 (any)';
        break;
      default:
        summary = vals.summary || '설정됨';
    }
    onSave(summary, vals);
  };

  return (
    <>
      {renderFields(type, vals, set, connectedTables)}
      <div className="cfg-ft">
        <button className="cfg-btn save" onClick={handleSave}>저장</button>
        <button className="cfg-btn" onClick={onClose}>닫기</button>
      </div>
    </>
  );
}

function renderFields(
  type: string,
  vals: Record<string, any>,
  set: (k: string, v: any) => void,
  tables: Record<string, any>[],
) {
  switch (type) {
    /* ─── Phase 2 schema-driven 4종 ─── */
    case 'condition':
      return (
        <>
          <CfgSec label="필드">
            <FieldPicker tables={tables} value={vals.field} onChange={(f) => set('field', f)}
              placeholder="비교할 컬럼 선택..." />
          </CfgSec>
          <CfgSec label="연산자">
            <CfgSelect value={vals.op ?? '='} onChange={(v) => set('op', v)}
              options={['=', '≠', '>', '<', '≥', '≤', '포함', '기한 경과']} />
          </CfgSec>
          <CfgSec label="값">
            <ValuePicker tables={tables} fieldRef={vals.field} value={vals.value}
              onChange={(v) => set('value', v)} />
          </CfgSec>
        </>
      );
    case 'status-change':
      return (
        <>
          <CfgSec label="대상 테이블">
            <TablePicker tables={tables} value={vals.table} onChange={(v) => set('table', v)} />
          </CfgSec>
          <CfgSec label="변경 필드">
            <FieldPicker tables={tables} value={vals.field} onChange={(f) => set('field', f)}
              placeholder="변경할 컬럼 선택..." />
          </CfgSec>
          <CfgSec label="변경값">
            <ValuePicker tables={tables} fieldRef={vals.field} value={vals.value}
              onChange={(v) => set('value', v)} placeholder="새 값" />
          </CfgSec>
        </>
      );
    case 'calculation':
      return (
        <>
          <CfgSec label="대상 테이블">
            <TablePicker tables={tables} value={vals.table} onChange={(v) => set('table', v)} />
          </CfgSec>
          <CfgSec label="결과 필드">
            <FieldPicker tables={tables} value={vals.field} onChange={(f) => set('field', f)}
              placeholder="저장할 컬럼 선택..." />
          </CfgSec>
          <CfgSec label="수식">
            <CfgInput value={vals.formula ?? ''} onChange={(v) => set('formula', v)}
              placeholder="QTY * UNIT_PRICE" />
          </CfgSec>
        </>
      );
    case 'validation':
      return (
        <>
          <CfgSec label="대상 필드">
            <FieldPicker tables={tables} value={vals.field} onChange={(f) => set('field', f)}
              placeholder="검증할 컬럼 선택..." />
          </CfgSec>
          <CfgSec label="검증 규칙">
            <CfgSelect value={vals.rule ?? '필수값 (NOT NULL)'} onChange={(v) => set('rule', v)}
              options={['필수값 (NOT NULL)', '범위 체크', '정규식 매칭', '참조 무결성', '커스텀 조건']} />
          </CfgSec>
        </>
      );

    /* ─── 기존 케이스 유지 (테이블 컬럼 의존성 없는 노드들) ─── */
    case 'auto-insert':
      return (
        <CfgSec label="대상 테이블">
          <TablePicker tables={tables} value={vals.table} onChange={(v) => set('table', v)} />
        </CfgSec>
      );
    case 'timer':
      return (
        <>
          <CfgSec label="기준 필드">
            <FieldPicker tables={tables} value={vals.field} onChange={(f) => set('field', f)}
              placeholder="시간 기준 컬럼..." />
          </CfgSec>
          <CfgSec label="경과 기준">
            <div style={{ display: 'flex', gap: '.3rem' }}>
              <CfgInput value={vals.amount ?? '0'} onChange={(v) => set('amount', v)} placeholder="0" />
              <CfgSelect value={vals.unit ?? '일'} onChange={(v) => set('unit', v)} options={['일', '시간', '주']} />
            </div>
          </CfgSec>
        </>
      );
    case 'notification':
      return (
        <>
          <CfgSec label="채널">
            <CfgSelect value={vals.channel ?? '이메일'} onChange={(v) => set('channel', v)}
              options={['이메일', 'SMS', '푸시', 'Slack']} />
          </CfgSec>
          <CfgSec label="수신자">
            <CfgSelect value={vals.target ?? '담당자'} onChange={(v) => set('target', v)}
              options={['담당자', '관리자', '전체']} />
          </CfgSec>
          <CfgSec label="메시지">
            <textarea className="cfg-ta" rows={2} value={vals.message ?? ''}
              onChange={(e) => set('message', e.target.value)} />
          </CfgSec>
        </>
      );
    case 'approval':
      return (
        <>
          <CfgSec label="승인자">
            <CfgSelect value={vals.approver ?? '팀장'} onChange={(v) => set('approver', v)}
              options={['팀장', '부서장', '관리자', '지정 사용자']} />
          </CfgSec>
          <CfgSec label="승인 조건">
            <CfgInput value={vals.condition ?? ''} onChange={(v) => set('condition', v)} placeholder="조건식" />
          </CfgSec>
        </>
      );
    case 'webhook':
      return (
        <>
          <CfgSec label="URL">
            <CfgInput value={vals.url ?? ''} onChange={(v) => set('url', v)} placeholder="https://..." />
          </CfgSec>
          <CfgSec label="메서드">
            <CfgSelect value={vals.method ?? 'POST'} onChange={(v) => set('method', v)}
              options={['POST', 'GET', 'PUT', 'DELETE']} />
          </CfgSec>
        </>
      );
    case 'log':
      return (
        <>
          <CfgSec label="로그 레벨">
            <CfgSelect value={vals.level ?? 'info'} onChange={(v) => set('level', v)}
              options={['info', 'warn', 'error', 'debug']} />
          </CfgSec>
          <CfgSec label="내용">
            <CfgInput value={vals.content ?? ''} onChange={(v) => set('content', v)} placeholder="액션 설명" />
          </CfgSec>
        </>
      );
    case 'delete':
      return (
        <>
          <CfgSec label="대상 테이블">
            <TablePicker tables={tables} value={vals.table} onChange={(v) => set('table', v)} />
          </CfgSec>
          <CfgSec label="삭제 방식">
            <CfgSelect value={vals.mode ?? 'soft'} onChange={(v) => set('mode', v)}
              options={['soft', 'hard']} />
          </CfgSec>
          <CfgSec label="조건 (WHERE)">
            <CfgInput value={vals.where ?? ''} onChange={(v) => set('where', v)} placeholder="id = ?" />
          </CfgSec>
        </>
      );
    case 'document':
      return (
        <>
          <CfgSec label="템플릿">
            <CfgInput value={vals.template ?? ''} onChange={(v) => set('template', v)} placeholder="출고확인서.docx" />
          </CfgSec>
          <CfgSec label="출력 경로">
            <CfgInput value={vals.output ?? ''} onChange={(v) => set('output', v)} placeholder="/docs/{id}.pdf" />
          </CfgSec>
          <CfgSec label="포맷">
            <CfgSelect value={vals.format ?? 'pdf'} onChange={(v) => set('format', v)}
              options={['pdf', 'docx', 'xlsx', 'html']} />
          </CfgSec>
        </>
      );
    case 'delay':
      return (
        <CfgSec label="지연 시간">
          <div style={{ display: 'flex', gap: '.3rem' }}>
            <CfgInput value={vals.amount ?? '0'} onChange={(v) => set('amount', v)} placeholder="0" />
            <CfgSelect value={vals.unit ?? '분'} onChange={(v) => set('unit', v)}
              options={['초', '분', '시간', '일']} />
          </div>
        </CfgSec>
      );
    case 'loop':
      return (
        <>
          <CfgSec label="반복 방식">
            <CfgSelect value={vals.mode ?? 'count'} onChange={(v) => set('mode', v)}
              options={['count', 'forEach', 'while']} />
          </CfgSec>
          {vals.mode === 'forEach' ? (
            <CfgSec label="반복 대상 필드">
              <FieldPicker tables={tables} value={vals.iterField} onChange={(f) => set('iterField', f)} />
            </CfgSec>
          ) : vals.mode === 'while' ? (
            <CfgSec label="조건식">
              <CfgInput value={vals.condition ?? ''} onChange={(v) => set('condition', v)} placeholder="x < 10" />
            </CfgSec>
          ) : (
            <CfgSec label="횟수">
              <CfgInput value={vals.count ?? '1'} onChange={(v) => set('count', v)} placeholder="1" />
            </CfgSec>
          )}
        </>
      );
    case 'parallel':
      return (
        <CfgSec label="병렬 분기 수">
          <CfgInput value={vals.branches ?? '2'} onChange={(v) => set('branches', v)} placeholder="2" />
        </CfgSec>
      );
    case 'merge':
      return (
        <CfgSec label="합류 전략">
          <CfgSelect value={vals.strategy ?? 'any'} onChange={(v) => set('strategy', v)}
            options={['any', 'all']} />
        </CfgSec>
      );
    default:
      return <div className="cfg-sec" style={{ color: 'var(--v5-text-muted)', fontSize: '.55rem' }}>설정 없음</div>;
  }
}

/* ─── 공통 atoms ─── */

function CfgSec({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="cfg-sec">
      <label className="cfg-lb">{label}</label>
      {children}
    </div>
  );
}

function CfgInput({ value, onChange, placeholder }: { value: string; onChange: (v: string) => void; placeholder?: string }) {
  return (
    <input className="cfg-inp" value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder} />
  );
}

function CfgSelect({ value, onChange, options }: { value: string; onChange: (v: string) => void; options: string[] }) {
  return (
    <select className="cfg-sel" value={value} onChange={(e) => onChange(e.target.value)}>
      {options.map((o) => <option key={o} value={o}>{o}</option>)}
    </select>
  );
}
