import type { OHLCVBar } from '../types';

export interface PriceStats {
  current: number;
  change: number;
  changePct: number;
  high52w: number;
  low52w: number;
  avgVol: number;
  avgRange: number;
  volatility: number;    // annualized std dev of returns (%)
  rrsi14: number;        // rough RSI(14) approximation
  pivotH: number;        // classic pivot points
  pivotL: number;
  pivotP: number;
  support1: number;
  support2: number;
  resistance1: number;
  resistance2: number;
  trend: 'up' | 'down' | 'sideways';
}

export function calcStats(bars: OHLCVBar[]): PriceStats {
  if (bars.length < 2) {
    return {
      current: 0, change: 0, changePct: 0,
      high52w: 0, low52w: 0, avgVol: 0, avgRange: 0,
      volatility: 0, rrsi14: 50,
      pivotH: 0, pivotL: 0, pivotP: 0,
      support1: 0, support2: 0, resistance1: 0, resistance2: 0,
      trend: 'sideways',
    };
  }

  const last = bars[bars.length - 1];
  const prev = bars[bars.length - 2];
  const change = last.close - prev.close;
  const changePct = change / prev.close * 100;

  const lookback = Math.min(bars.length, 252);
  const slice = bars.slice(-lookback);

  const high52w = Math.max(...slice.map(b => b.high));
  const low52w  = Math.min(...slice.map(b => b.low));
  const avgVol  = slice.reduce((s, b) => s + b.volume, 0) / slice.length;
  const avgRange= slice.reduce((s, b) => s + (b.high - b.low), 0) / slice.length;

  // Annualized volatility
  const returns = slice.slice(1).map((b, i) => Math.log(b.close / slice[i].close));
  const mean = returns.reduce((s, r) => s + r, 0) / returns.length;
  const variance = returns.reduce((s, r) => s + (r - mean) ** 2, 0) / returns.length;
  const volatility = Math.sqrt(variance * 252) * 100;

  // Rough RSI(14)
  const rsiSlice = bars.slice(-15);
  let gains = 0, losses = 0;
  for (let i = 1; i < rsiSlice.length; i++) {
    const d = rsiSlice[i].close - rsiSlice[i - 1].close;
    if (d > 0) gains += d; else losses -= d;
  }
  const avgGain = gains / 14;
  const avgLoss = losses / 14;
  const rrsi14 = avgLoss === 0 ? 100 : 100 - 100 / (1 + avgGain / avgLoss);

  // Classic Pivot Points (from last bar)
  const pivotH = last.high;
  const pivotL = last.low;
  const pivotP = (last.high + last.low + last.close) / 3;
  const resistance1 = 2 * pivotP - last.low;
  const support1    = 2 * pivotP - last.high;
  const resistance2 = pivotP + (last.high - last.low);
  const support2    = pivotP - (last.high - last.low);

  // Trend (20-bar EMA vs 50-bar EMA)
  const ema20 = calcEMA(bars.map(b => b.close), 20);
  const ema50 = calcEMA(bars.map(b => b.close), 50);
  const e20 = ema20[ema20.length - 1];
  const e50 = ema50[ema50.length - 1];
  const trend = e20 > e50 * 1.002 ? 'up' : e20 < e50 * 0.998 ? 'down' : 'sideways';

  return {
    current: last.close, change, changePct,
    high52w, low52w, avgVol, avgRange, volatility, rrsi14,
    pivotH, pivotL, pivotP,
    support1, support2, resistance1, resistance2,
    trend,
  };
}

function calcEMA(prices: number[], period: number): number[] {
  const k = 2 / (period + 1);
  const result: number[] = [];
  let ema = prices[0];
  for (const p of prices) {
    ema = p * k + ema * (1 - k);
    result.push(ema);
  }
  return result;
}

/** Auto-calculate Fibonacci retracement levels from visible data */
export function calcAutoFib(bars: OHLCVBar[], lookback = 50): {
  high: number; low: number; highTime: number; lowTime: number;
  levels: Array<{ ratio: number; price: number; label: string }>;
} {
  const slice = bars.slice(-lookback);
  let high = -Infinity, low = Infinity, highTime = 0, lowTime = 0;
  for (const b of slice) {
    if (b.high > high)  { high = b.high; highTime = b.time; }
    if (b.low  < low)   { low  = b.low;  lowTime  = b.time; }
  }
  const range = high - low;
  const LEVELS = [
    { ratio: 0,     label: '0%' },
    { ratio: 0.236, label: '23.6%' },
    { ratio: 0.382, label: '38.2%' },
    { ratio: 0.5,   label: '50%' },
    { ratio: 0.618, label: '61.8%' },
    { ratio: 0.786, label: '78.6%' },
    { ratio: 1,     label: '100%' },
    { ratio: 1.272, label: '127.2%' },
    { ratio: 1.618, label: '161.8%' },
  ];
  return {
    high, low, highTime, lowTime,
    levels: LEVELS.map(l => ({ ...l, price: high - range * l.ratio })),
  };
}
