import type { OHLCVBar } from './types';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
import type { Bar } from 'oakscriptjs';

export type IndicatorCategory =
  | 'Moving Averages'
  | 'Oscillators'
  | 'Momentum'
  | 'Trend'
  | 'Volatility'
  | 'Channels & Bands'
  | 'Volume'
  | 'Candlestick Patterns';

export interface PlotDef {
  id: string;
  title: string;
  color: string;
  type: 'line' | 'histogram' | 'area' | 'scatter';
  lineWidth?: number;
}

export interface HLineDef { price: number; color: string; }

export interface IndicatorDef {
  type: string;
  name: string;
  shortName: string;
  category: IndicatorCategory;
  overlay: boolean;
  defaultParams: Record<string, number | string | boolean>;
  plots: PlotDef[];
  hlines?: HLineDef[];
  returnsMarkers?: boolean;
  description: string;
}

export const INDICATOR_REGISTRY: IndicatorDef[] = [
  { type:'SMA',    name:'Simple Moving Average',            shortName:'SMA',    category:'Moving Averages', overlay:true,  defaultParams:{len:20, src:'close'},                     plots:[{id:'plot0',title:'SMA',   color:'#2962FF',type:'line',lineWidth:2}],   description:'단순 이동평균' },
  { type:'EMA',    name:'Exponential Moving Average',       shortName:'EMA',    category:'Moving Averages', overlay:true,  defaultParams:{length:21, src:'close'},                  plots:[{id:'plot0',title:'EMA',   color:'#FF6D00',type:'line',lineWidth:2}],   description:'지수 이동평균' },
  { type:'WMA',    name:'Weighted Moving Average',          shortName:'WMA',    category:'Moving Averages', overlay:true,  defaultParams:{length:20, src:'close'},                  plots:[{id:'plot0',title:'WMA',   color:'#00BCD4',type:'line',lineWidth:2}],   description:'가중 이동평균' },
  { type:'BollingerBands', name:'Bollinger Bands',          shortName:'BB',     category:'Channels & Bands', overlay:true, defaultParams:{length:20, mult:2, src:'close'},          plots:[{id:'plot0',title:'Upper', color:'#2196F320',type:'line',lineWidth:1},{id:'plot1',title:'Basis',color:'#E91E63',type:'line',lineWidth:1},{id:'plot2',title:'Lower',color:'#2196F320',type:'line',lineWidth:1}], description:'볼린저 밴드' },
  { type:'RSI',    name:'Relative Strength Index',          shortName:'RSI',    category:'Oscillators', overlay:false, defaultParams:{length:14, src:'close'}, plots:[{id:'plot0',title:'RSI',color:'#7E57C2',type:'line',lineWidth:2}], hlines:[{price:70,color:'#EF5350'},{price:50,color:'#607D8B'},{price:30,color:'#4CAF50'}], description:'상대 강도 지수' },
  { type:'MACD',   name:'MACD',                             shortName:'MACD',   category:'Momentum', overlay:false, defaultParams:{fastLength:12, slowLength:26, signalLength:9, src:'close'}, plots:[{id:'plot0',title:'Histogram',color:'#26A69A',type:'histogram'},{id:'plot1',title:'MACD',color:'#2962FF',type:'line',lineWidth:1},{id:'plot2',title:'Signal',color:'#FF6D00',type:'line',lineWidth:1}], hlines:[{price:0,color:'#607D8B'}], description:'이동평균 수렴·발산' },
  { type:'Stochastic', name:'Stochastic',                   shortName:'Stoch',  category:'Oscillators', overlay:false, defaultParams:{kLength:14, dSmoothing:3, smooth:3}, plots:[{id:'plot0',title:'%K',color:'#2196F3',type:'line',lineWidth:1},{id:'plot1',title:'%D',color:'#FF6D00',type:'line',lineWidth:1}], hlines:[{price:80,color:'#EF5350'},{price:20,color:'#4CAF50'}], description:'스토캐스틱' },
  { type:'CCI',    name:'Commodity Channel Index',          shortName:'CCI',    category:'Oscillators', overlay:false, defaultParams:{length:20, src:'hlc3'}, plots:[{id:'plot0',title:'CCI',color:'#00BCD4',type:'line',lineWidth:2}], hlines:[{price:100,color:'#EF5350'},{price:0,color:'#607D8B'},{price:-100,color:'#4CAF50'}], description:'상품 채널 지수' },
  { type:'ADX',    name:'Average Directional Index',        shortName:'ADX',    category:'Trend', overlay:false, defaultParams:{adxSmoothing:14, diLength:14}, plots:[{id:'plot0',title:'ADX',color:'#FF6D00',type:'line',lineWidth:2},{id:'plot1',title:'+DI',color:'#4CAF50',type:'line',lineWidth:1},{id:'plot2',title:'-DI',color:'#EF5350',type:'line',lineWidth:1}], hlines:[{price:25,color:'#607D8B'}], description:'평균 방향성 지수' },
  { type:'OBV',    name:'On Balance Volume',                shortName:'OBV',    category:'Volume', overlay:false, defaultParams:{}, plots:[{id:'plot0',title:'OBV',color:'#2196F3',type:'line',lineWidth:2}], description:'잔량 균형 지수' },
  { type:'DMI',    name:'Directional Movement Index',       shortName:'DMI',    category:'Trend', overlay:false, defaultParams:{length:14}, plots:[{id:'plot0',title:'+DI',color:'#4CAF50',type:'line',lineWidth:2},{id:'plot1',title:'-DI',color:'#EF5350',type:'line',lineWidth:2},{id:'plot2',title:'DX',color:'#FF9800',type:'line',lineWidth:1}], hlines:[{price:25,color:'#607D8B'}], description:'방향성 이동 지수' },
  { type:'WilliamsPercentRange', name:'Williams %R',        shortName:'W%R',    category:'Oscillators', overlay:false, defaultParams:{length:14}, plots:[{id:'plot0',title:'%R',color:'#9C27B0',type:'line',lineWidth:2}], hlines:[{price:-20,color:'#EF5350'},{price:-50,color:'#607D8B'},{price:-80,color:'#4CAF50'}], description:'윌리엄스 %R' },
  { type:'TRIX',   name:'TRIX',                             shortName:'TRIX',   category:'Momentum', overlay:false, defaultParams:{length:18, signalLength:9, src:'close'}, plots:[{id:'plot0',title:'TRIX',color:'#4CAF50',type:'line',lineWidth:2},{id:'plot1',title:'Signal',color:'#FF6D00',type:'line',lineWidth:1}], hlines:[{price:0,color:'#607D8B'}], description:'삼중 지수 변화율' },
  { type:'VolumeOscillator', name:'Volume Oscillator',      shortName:'VO',     category:'Volume', overlay:false, defaultParams:{shortLength:5, longLength:10}, plots:[{id:'plot0',title:'VO',color:'#FF7043',type:'histogram'}], hlines:[{price:0,color:'#607D8B'}], description:'볼륨 오실레이터' },
  { type:'IchimokuCloud', name:'Ichimoku Cloud',            shortName:'Ichi',   category:'Trend', overlay:true,  defaultParams:{conversionPeriods:9, basePeriods:26, laggingSpan2Periods:52, displacement:26}, plots:[{id:'plot0',title:'Tenkan',color:'#2196F3',type:'line',lineWidth:1},{id:'plot1',title:'Kijun',color:'#EF5350',type:'line',lineWidth:1},{id:'plot2',title:'SpanA',color:'#4CAF50',type:'line',lineWidth:1},{id:'plot3',title:'SpanB',color:'#EF5350',type:'line',lineWidth:1},{id:'plot4',title:'Lagging',color:'#9C27B0',type:'line',lineWidth:1}], description:'일목균형표' },
];

export function getIndicatorDef(type: string): IndicatorDef | undefined {
  return INDICATOR_REGISTRY.find(d => d.type === type);
}

export function toBars(ohlcv: OHLCVBar[]): Bar[] {
  return ohlcv as unknown as Bar[];
}

export type PlotData = Array<{ time: number; value: number; color?: string }>;
export type IndicatorResult = Record<string, PlotData>;

export interface MarkerData {
  time: number;
  position: 'aboveBar' | 'belowBar';
  shape: 'arrowUp' | 'arrowDown' | 'circle' | 'square';
  color: string;
  text: string;
}

export async function calculateIndicator(
  type: string,
  bars: OHLCVBar[],
  params: Record<string, number | string | boolean>
): Promise<{ plots: IndicatorResult; markers?: MarkerData[] }> {
  const b = toBars(bars);
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const lib = await import('lightweight-charts-indicators-v5') as any;
  const ind = (lib as unknown as Record<string, {
    calculate: (b: Bar[], p: unknown) => { plots?: Record<string, PlotData>; markers?: MarkerData[] }
  }>)[type];
  if (!ind?.calculate) throw new Error(`Unknown indicator: ${type}`);
  const result = ind.calculate(b, params);
  return {
    plots: (result.plots ?? {}) as IndicatorResult,
    markers: result.markers as MarkerData[] | undefined,
  };
}
