import { applyCosts } from './costs.js';

function atr14(candles, period = 14) {
  if (!candles || candles.length <= period) return null;
  const trs = [];
  for (let i = 1; i < candles.length; i++) {
    const { high, low } = candles[i];
    const prevClose = candles[i - 1].close;
    trs.push(Math.max(high - low, Math.abs(high - prevClose), Math.abs(low - prevClose)));
  }
  const recent = trs.slice(-period);
  return recent.reduce((a, b) => a + b, 0) / recent.length;
}

export function simulateSwing(candles, entryIdx, cfg) {
  // If entry is impossible (out of bounds)
  if (entryIdx >= candles.length) return null;

  const rawEntry = candles[entryIdx].open;
  const entry = applyCosts(rawEntry, 'buy', candles, entryIdx);
  
  // ATR known at signal (close of previous day). candles slice goes UP TO the entryIdx (so it includes the signal bar, which is entryIdx - 1)
  // Wait, if entryIdx is the open of tomorrow, we pass candles.slice(0, entryIdx) so the last candle is today (the signal bar).
  const preEntryCandles = candles.slice(0, entryIdx);
  const atr = atr14(preEntryCandles);
  if (!atr) return null;

  const stop = entry - cfg.stopAtr * atr;
  const target = entry + cfg.targetAtr * atr;
  const R = entry - stop; // 1 ATR worth of price

  const end = Math.min(entryIdx + cfg.maxHoldDays - 1, candles.length - 1);
  
  for (let d = entryIdx; d <= end; d++) {
    // pessimistic tie-break: if both hit same day, assume STOP first
    if (candles[d].low <= stop) return { outcome: 'LOSS', r: -1.0, exitDay: d, stopPrice: stop, targetPrice: target, atr };
    if (candles[d].high >= target) return { outcome: 'WIN', r: cfg.targetAtr, exitDay: d, stopPrice: stop, targetPrice: target, atr };
  }
  
  // unresolved → exit at close of last day, net of exit costs
  const rawExit = candles[end].close;
  const exit = applyCosts(rawExit, 'sell', candles, end);
  return { outcome: 'SCRATCH', r: (exit - entry) / R, exitDay: end, stopPrice: stop, targetPrice: target, atr };
}
