// ── DSL 트리 타입 ─────────────────────────────────────────────────────────────

export type LogicNodeType = 'AND' | 'OR' | 'NOT' | 'CONDITION' | 'TIMEFRAME';

export interface ConditionDSL {
  indicatorType: string;
  conditionType:  string;
  targetValue?:   number;
  period?:        number;
  /** 복합지표 — 동일 지표 2기간 교차 */
  composite?:     boolean;
  leftPeriod?:    number;
  rightPeriod?:   number;
  leftField?:     string;
  rightField?:    string;
  compareValue?:  number;
  slopePeriod?:   number;
  holdDays?:      number;
  candleRange?:   number;
}

export interface LogicNode {
  id:          string;
  type:        LogicNodeType;
  children?:   LogicNode[];
  condition?:  ConditionDSL;
  description?: string;
  /** TIMEFRAME 노드 — 조건 판별 대상 캔들 타입 (1m, 5m, 1h …) */
  candleType?: string;
}

export interface StrategyDSLDto {
  id?:           number;
  name:          string;
  description?:  string;
  buyCondition?:  LogicNode | null;
  sellCondition?: LogicNode | null;
  enabled?:      boolean;
  createdAt?:    string;
  updatedAt?:    string;
}

// ── 지표별 조건 옵션 ──────────────────────────────────────────────────────────

export const CONDITION_LABEL: Record<string, string> = {
  GT: '초과(>)', LT: '미만(<)', GTE: '이상(≥)', LTE: '이하(≤)',
  EQ: '같음(=)', NEQ: '다름(≠)',
  CROSS_UP: '상향 돌파', CROSS_DOWN: '하향 돌파',
  SLOPE_UP: '상승 중', SLOPE_DOWN: '하락 중',
  DIFF_GT: '차이>값', DIFF_LT: '차이<값',
  HOLD_N_DAYS: 'N일 유지',
  ABOVE_CLOUD: '구름 위', BELOW_CLOUD: '구름 아래', IN_CLOUD: '구름 안',
  CLOUD_BREAK_UP: '구름 상향 돌파', CLOUD_BREAK_DOWN: '구름 하향 돌파',
  SPAN1_GT_SPAN2: '선행1>선행2', SPAN1_LT_SPAN2: '선행1<선행2',
  SPAN1_CROSS_UP_SPAN2: '선행1 상향교차', SPAN1_CROSS_DOWN_SPAN2: '선행1 하향교차',
  LAGGING_GT_PRICE: '후행>종가', LAGGING_LT_PRICE: '후행<종가',
};

const COMMON_CONDITIONS = ['GT', 'LT', 'GTE', 'LTE', 'EQ', 'NEQ', 'CROSS_UP', 'CROSS_DOWN', 'SLOPE_UP', 'SLOPE_DOWN', 'DIFF_GT', 'DIFF_LT', 'HOLD_N_DAYS'];

export const INDICATOR_CONDITIONS: Record<string, string[]> = {
  RSI: COMMON_CONDITIONS, MACD: COMMON_CONDITIONS, CCI: COMMON_CONDITIONS,
  ADX: COMMON_CONDITIONS, BWI: COMMON_CONDITIONS, DMI: COMMON_CONDITIONS,
  OBV: COMMON_CONDITIONS, STOCHASTIC: COMMON_CONDITIONS, WILLIAMS_R: COMMON_CONDITIONS,
  TRIX: COMMON_CONDITIONS, VOLUME_OSC: COMMON_CONDITIONS, VR: COMMON_CONDITIONS,
  DISPARITY: COMMON_CONDITIONS, PSYCHOLOGICAL: COMMON_CONDITIONS,
  NEW_PSYCHOLOGICAL: COMMON_CONDITIONS, INVEST_PSYCHOLOGICAL: COMMON_CONDITIONS,
  VOLUME: COMMON_CONDITIONS,
  MA: COMMON_CONDITIONS, EMA: COMMON_CONDITIONS,
  BOLLINGER: COMMON_CONDITIONS,
  DONCHIAN: COMMON_CONDITIONS,
  ICHIMOKU: [
    ...COMMON_CONDITIONS,
    'ABOVE_CLOUD', 'BELOW_CLOUD', 'IN_CLOUD', 'CLOUD_BREAK_UP', 'CLOUD_BREAK_DOWN',
    'SPAN1_GT_SPAN2', 'SPAN1_LT_SPAN2', 'SPAN1_CROSS_UP_SPAN2', 'SPAN1_CROSS_DOWN_SPAN2',
    'LAGGING_GT_PRICE', 'LAGGING_LT_PRICE',
  ],
};

// ── 지표별 leftField 옵션 ───────────────────────────────────────────────────

export type FieldOption = { value: string; label: string };

export const LEFT_FIELD_OPTIONS: Record<string, FieldOption[]> = {
  RSI:                 [{ value: 'CURRENT', label: '현재 캔들' }],
  CCI:                 [{ value: 'CURRENT', label: '현재 캔들' }],
  ADX:                 [{ value: 'CURRENT', label: '현재 캔들' }],
  BWI:                 [{ value: 'CURRENT', label: '현재 캔들' }],
  DMI:                 [{ value: 'CURRENT', label: '현재 캔들' }, { value: 'PLUS_DI', label: '+DI' }, { value: 'MINUS_DI', label: '-DI' }],
  OBV:                 [{ value: 'CURRENT', label: 'OBV' }],
  STOCHASTIC:          [{ value: 'K', label: '%K' }, { value: 'D', label: '%D' }],
  MACD:                [{ value: 'MACD', label: 'MACD선' }, { value: 'SIGNAL', label: '시그널선' }, { value: 'HISTOGRAM', label: '히스토그램' }],
  WILLIAMS_R:          [{ value: 'CURRENT', label: '현재 캔들' }],
  TRIX:                [{ value: 'TRIX', label: 'TRIX' }, { value: 'SIGNAL', label: '시그널' }],
  VOLUME_OSC:          [{ value: 'CURRENT', label: 'VolumeOSC' }],
  VR:                  [{ value: 'CURRENT', label: 'VR' }],
  DISPARITY:           [{ value: 'CURRENT', label: '이격도' }],
  PSYCHOLOGICAL:        [{ value: 'CURRENT', label: '심리도' }],
  NEW_PSYCHOLOGICAL:    [{ value: 'CURRENT', label: '심리도' }],
  INVEST_PSYCHOLOGICAL: [{ value: 'CURRENT', label: '투자심리도' }],
  VOLUME:              [{ value: 'CURRENT', label: '거래량' }],
  MA: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'MA5',  label: 'MA(5일)'  }, { value: 'MA10', label: 'MA(10일)' },
    { value: 'MA20', label: 'MA(20일)' }, { value: 'MA60', label: 'MA(60일)' },
    { value: 'MA120',label: 'MA(120일)'},
  ],
  EMA: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'EMA5',  label: 'EMA(5일)'  }, { value: 'EMA10', label: 'EMA(10일)' },
    { value: 'EMA20', label: 'EMA(20일)' }, { value: 'EMA60', label: 'EMA(60일)' },
  ],
  BOLLINGER: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'UPPER', label: '상단밴드' }, { value: 'MIDDLE', label: '중단밴드' },
    { value: 'LOWER', label: '하단밴드' },
  ],
  DONCHIAN: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'LOW_PRICE', label: '저가' },
    { value: 'HIGH_PRICE', label: '고가' },
  ],
  ICHIMOKU: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'CONVERSION_LINE', label: '전환선' }, { value: 'BASE_LINE', label: '기준선' },
    { value: 'LEADING_SPAN1', label: '선행1' },    { value: 'LEADING_SPAN2', label: '선행2' },
    { value: 'LAGGING_SPAN', label: '후행스팬' },
  ],
};

export const RIGHT_FIELD_OPTIONS: Record<string, FieldOption[]> = {
  RSI: [
    { value: 'OVERBOUGHT_70', label: '과매수(70)' }, { value: 'OVERBOUGHT_75', label: '과매수(75)' },
    { value: 'NEUTRAL_50',    label: '중립(50)'    }, { value: 'OVERSOLD_30',   label: '과매도(30)'  },
    { value: 'OVERSOLD_25',   label: '과매도(25)'  }, { value: 'CUSTOM',        label: '직접 입력'  },
  ],
  CCI: [
    { value: 'OVERBOUGHT_100', label: '과매수(100)' }, { value: 'NEUTRAL_0',       label: '중립(0)'    },
    { value: 'OVERSOLD_NEG100',label: '과매도(-100)'},  { value: 'CUSTOM',          label: '직접 입력'  },
  ],
  STOCHASTIC: [
    { value: 'OVERBOUGHT_80', label: '과매수(80)' }, { value: 'NEUTRAL_50',  label: '중립(50)'  },
    { value: 'OVERSOLD_20',   label: '과매도(20)' }, { value: 'K',           label: '%K'        },
    { value: 'D',             label: '%D'          }, { value: 'CUSTOM',      label: '직접 입력' },
  ],
  MACD: [
    { value: 'SIGNAL', label: '시그널선' }, { value: 'ZERO_LINE', label: '0선' },
    { value: 'CUSTOM', label: '직접 입력' },
  ],
  WILLIAMS_R: [
    { value: 'OVERBOUGHT_NEG20', label: '과매수(-20)' }, { value: 'NEUTRAL_NEG50', label: '중립(-50)' },
    { value: 'OVERSOLD_NEG80',   label: '과매도(-80)' }, { value: 'CUSTOM',        label: '직접 입력' },
  ],
  ADX: [
    { value: 'ADX_25', label: '강한추세(25)' }, { value: 'ADX_20', label: '약한추세(20)' },
    { value: 'CUSTOM', label: '직접 입력' },
  ],
  PSYCHOLOGICAL: [
    { value: 'OVERBOUGHT_75', label: '과매수(75)' }, { value: 'NEUTRAL_50', label: '중립(50)' },
    { value: 'OVERSOLD_25',   label: '과매도(25)' }, { value: 'CUSTOM',     label: '직접 입력' },
  ],
  NEW_PSYCHOLOGICAL: [
    { value: 'OVERBOUGHT_75', label: '과매수(75)' }, { value: 'NEUTRAL_50', label: '중립(50)' },
    { value: 'OVERSOLD_25',   label: '과매도(25)' }, { value: 'CUSTOM',     label: '직접 입력' },
  ],
  INVEST_PSYCHOLOGICAL: [
    { value: 'OVERBOUGHT_75', label: '과매수(75)' }, { value: 'NEUTRAL_50', label: '중립(50)' },
    { value: 'OVERSOLD_25',   label: '과매도(25)' }, { value: 'CUSTOM',     label: '직접 입력' },
  ],
  TRIX: [
    { value: 'SIGNAL', label: '시그널' }, { value: 'ZERO_LINE', label: '0선' }, { value: 'CUSTOM', label: '직접 입력' },
  ],
  VR: [
    { value: 'OVERBOUGHT_200', label: '과매수(200)' }, { value: 'NEUTRAL_100', label: '기준(100)' },
    { value: 'OVERSOLD_70',    label: '과매도(70)'  }, { value: 'CUSTOM',      label: '직접 입력' },
  ],
  MA: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'MA5',  label: 'MA(5일)'  }, { value: 'MA10', label: 'MA(10일)' },
    { value: 'MA20', label: 'MA(20일)' }, { value: 'MA60', label: 'MA(60일)' },
    { value: 'MA120',label: 'MA(120일)'}, { value: 'CUSTOM', label: '직접 입력' },
  ],
  EMA: [
    { value: 'CLOSE_PRICE', label: '종가' },
    { value: 'EMA5', label: 'EMA(5일)' }, { value: 'EMA10', label: 'EMA(10일)' },
    { value: 'EMA20', label: 'EMA(20일)' }, { value: 'EMA60', label: 'EMA(60일)' },
    { value: 'CUSTOM', label: '직접 입력' },
  ],
  BOLLINGER: [
    { value: 'UPPER', label: '상단밴드' }, { value: 'MIDDLE', label: '중단밴드' },
    { value: 'LOWER', label: '하단밴드' }, { value: 'CUSTOM', label: '직접 입력' },
  ],
  DONCHIAN: [
    { value: 'DC_UPPER_10', label: '상단(10일 최고가)' },
    { value: 'DC_UPPER_20', label: '상단(20일 최고가)' },
    { value: 'DC_UPPER_55', label: '상단(55일 최고가)' },
    { value: 'DC_MIDDLE_20', label: '중심(20일)' },
    { value: 'DC_LOWER_10', label: '하단(10일 최저가)' },
    { value: 'DC_LOWER_20', label: '하단(20일 최저가)' },
    { value: 'DC_LOWER_55', label: '하단(55일 최저가)' },
    { value: 'CUSTOM', label: '직접 입력' },
  ],
  ICHIMOKU: [
    { value: 'CONVERSION_LINE', label: '전환선' }, { value: 'BASE_LINE', label: '기준선' },
    { value: 'LEADING_SPAN1', label: '선행1' },    { value: 'LEADING_SPAN2', label: '선행2' },
    { value: 'LAGGING_SPAN',  label: '후행스팬' }, { value: 'CLOSE_PRICE',   label: '종가'   },
  ],
  VOLUME:    [{ value: 'MA5', label: 'MA(5일)' }, { value: 'MA20', label: 'MA(20일)' }, { value: 'CUSTOM', label: '직접 입력' }],
  DISPARITY: [{ value: 'NEUTRAL_100', label: '기준(100)' }, { value: 'OVERBOUGHT_105', label: '과매수(105)' }, { value: 'OVERSOLD_95', label: '과매도(95)' }, { value: 'CUSTOM', label: '직접 입력' }],
};

// ── 지표 목록 (팔레트용) ───────────────────────────────────────────────────

export interface PaletteItem {
  id:    string;
  type:  'operator' | 'indicator';
  label: string;
  value: string;
  color: 'green' | 'blue' | 'orange' | 'primary' | 'secondary';
}

export const OPERATOR_ITEMS: PaletteItem[] = [
  { id: 'op-and', type: 'operator', label: 'AND (그리고)', value: 'AND', color: 'green'  },
  { id: 'op-or',  type: 'operator', label: 'OR (또는)',    value: 'OR',  color: 'blue'   },
  { id: 'op-not', type: 'operator', label: 'NOT (반대)',   value: 'NOT', color: 'orange' },
];

export const MA_BAND_ITEMS: PaletteItem[] = [
  { id: 'ind-ma',       type: 'indicator', label: 'MA (이동평균)',    value: 'MA',       color: 'primary' },
  { id: 'ind-ema',      type: 'indicator', label: 'EMA (지수이동평균)', value: 'EMA',    color: 'primary' },
  { id: 'ind-bollinger',type: 'indicator', label: '볼린저밴드',        value: 'BOLLINGER', color: 'primary' },
  { id: 'ind-donchian', type: 'indicator', label: '돈치안 채널',       value: 'DONCHIAN',  color: 'primary' },
  { id: 'ind-ichimoku', type: 'indicator', label: '일목균형표',        value: 'ICHIMOKU',  color: 'primary' },
];

export const INDICATOR_ITEMS: PaletteItem[] = [
  { id: 'ind-psy',   type: 'indicator', label: '심리도',      value: 'PSYCHOLOGICAL',        color: 'secondary' },
  { id: 'ind-ipsy',  type: 'indicator', label: '투자심리도',  value: 'INVEST_PSYCHOLOGICAL', color: 'secondary' },
  { id: 'ind-macd',  type: 'indicator', label: 'MACD',        value: 'MACD',                 color: 'secondary' },
  { id: 'ind-cci',   type: 'indicator', label: 'CCI',         value: 'CCI',                  color: 'secondary' },
  { id: 'ind-adx',   type: 'indicator', label: 'ADX',         value: 'ADX',                  color: 'secondary' },
  { id: 'ind-bwi',   type: 'indicator', label: 'BWI',         value: 'BWI',                  color: 'secondary' },
  { id: 'ind-dmi',   type: 'indicator', label: 'DMI',         value: 'DMI',                  color: 'secondary' },
  { id: 'ind-obv',   type: 'indicator', label: 'OBV',         value: 'OBV',                  color: 'secondary' },
  { id: 'ind-rsi',   type: 'indicator', label: 'RSI',         value: 'RSI',                  color: 'secondary' },
  { id: 'ind-stoch', type: 'indicator', label: 'Stochastic',  value: 'STOCHASTIC',           color: 'secondary' },
  { id: 'ind-wr',    type: 'indicator', label: 'Williams %R', value: 'WILLIAMS_R',           color: 'secondary' },
  { id: 'ind-trix',  type: 'indicator', label: 'TRIX',        value: 'TRIX',                 color: 'secondary' },
  { id: 'ind-vosc',  type: 'indicator', label: 'VolumeOSC',   value: 'VOLUME_OSC',           color: 'secondary' },
  { id: 'ind-vr',    type: 'indicator', label: 'VR',          value: 'VR',                   color: 'secondary' },
  { id: 'ind-disp',  type: 'indicator', label: '이격도',       value: 'DISPARITY',            color: 'secondary' },
  { id: 'ind-vol',   type: 'indicator', label: '거래량',       value: 'VOLUME',               color: 'secondary' },
];

// ── 유틸 함수 ─────────────────────────────────────────────────────────────────

let _nodeCounter = 0;
export function generateNodeId(): string {
  return `node_${++_nodeCounter}_${Date.now()}`;
}

/** 자연어 설명 변환 */
export function nodeToNaturalLanguage(node: LogicNode): string {
  if (!node) return '';
  if (node.type === 'CONDITION' && node.condition) {
    const c = node.condition;
    const lOpts = LEFT_FIELD_OPTIONS[c.indicatorType] ?? [];
    const rOpts = RIGHT_FIELD_OPTIONS[c.indicatorType] ?? [];
    const leftLabel  = lOpts.find(o => o.value === c.leftField)?.label  ?? c.leftField  ?? c.indicatorType;
    const rightLabel = rOpts.find(o => o.value === c.rightField)?.label ?? c.rightField ?? '';
    const condLabel  = CONDITION_LABEL[c.conditionType] ?? c.conditionType;
    if (rightLabel && rightLabel !== '직접 입력') return `${leftLabel} ${condLabel} ${rightLabel}`;
    if (c.targetValue !== undefined) return `${leftLabel} ${condLabel} ${c.targetValue}`;
    return `${leftLabel} ${condLabel}`;
  }
  if (node.type === 'AND') {
    const parts = (node.children ?? []).map(c => nodeToNaturalLanguage(c));
    return parts.length === 0 ? '(AND 그룹)' : parts.join(' 그리고 ');
  }
  if (node.type === 'OR') {
    const parts = (node.children ?? []).map(c => nodeToNaturalLanguage(c));
    return parts.length === 0 ? '(OR 그룹)' : parts.join(' 또는 ');
  }
  if (node.type === 'NOT') {
    const child = node.children?.[0];
    return child ? `[아닌 경우] ${nodeToNaturalLanguage(child)}` : '(NOT 그룹)';
  }
  return '';
}

const STORAGE_KEY = 'gc_strategies_v1';

export function loadStrategiesFromStorage(): StrategyDSLDto[] {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    return raw ? JSON.parse(raw) : [];
  } catch { return []; }
}

export function saveStrategiesToStorage(strategies: StrategyDSLDto[]): void {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(strategies));
}
