// regime.jsx — market regime classifier
// Returns one of: TRENDING_UP, TRENDING_DOWN, SIDEWAYS, VOLATILE_NO_TREND

(function () {
  const { computeADX, computeSMA, computeATR, lastValue } = window.indicators;

  const REGIMES = {
    TRENDING_UP: 'TRENDING_UP',
    TRENDING_DOWN: 'TRENDING_DOWN',
    SIDEWAYS: 'SIDEWAYS',
    VOLATILE_NO_TREND: 'VOLATILE_NO_TREND',
  };

  function classifyRegime(closes, ohlc) {
    const high = ohlc?.high;
    const low = ohlc?.low;
    const hasOHLC = high && low && high.length === closes.length;

    let adxValue = null;
    if (hasOHLC) {
      const adxArr = computeADX(high, low, closes, 14);
      adxValue = lastValue(adxArr)?.adx ?? null;
    }

    if (adxValue == null) {
      const sma20 = computeSMA(closes, 20);
      if (sma20 && sma20.length >= 14) {
        const recent = sma20.slice(-14);
        const slopePerBar = (recent[recent.length - 1] - recent[0]) / (13 * recent[0]) * 100;
        adxValue = Math.abs(slopePerBar) * 15;
      }
    }

    const maPeriod = closes.length >= 200 ? 200 : 50;
    const maArr = computeSMA(closes, maPeriod);
    const maValue = lastValue(maArr);
    const lastClose = closes[closes.length - 1];

    let priceVsMa = 'near';
    if (maValue != null) {
      const pct = (lastClose - maValue) / maValue;
      if (pct > 0.03) priceVsMa = 'above';
      else if (pct < -0.03) priceVsMa = 'below';
    }

    let volatilePctile = 50;
    if (hasOHLC) {
      const atrArr = computeATR(high, low, closes, 14);
      if (atrArr && atrArr.length >= 50) {
        const atrSma = computeSMA(atrArr, 50);
        const currentAtr = lastValue(atrArr);
        const avgAtr = lastValue(atrSma);
        if (currentAtr != null && avgAtr != null && avgAtr > 0) {
          volatilePctile = (currentAtr / avgAtr) * 50;
        }
      }
    } else {
      return REGIMES.SIDEWAYS;
    }

    if (adxValue != null && adxValue > 25) {
      return priceVsMa === 'below' ? REGIMES.TRENDING_DOWN : REGIMES.TRENDING_UP;
    }
    if (volatilePctile > 75) {
      return REGIMES.VOLATILE_NO_TREND;
    }
    if (adxValue != null && adxValue < 20 && priceVsMa === 'near') {
      return REGIMES.SIDEWAYS;
    }
    if (adxValue != null && adxValue < 20) {
      return volatilePctile > 60 ? REGIMES.VOLATILE_NO_TREND : REGIMES.SIDEWAYS;
    }

    return REGIMES.SIDEWAYS;
  }

  const REGIME_MULTIPLIERS = {
    HEAD_SHOULDERS:     { TRENDING_UP: 1.15, TRENDING_DOWN: 0.75, SIDEWAYS: 0.85, VOLATILE_NO_TREND: 0.75 },
    INV_HEAD_SHOULDERS: { TRENDING_UP: 0.75, TRENDING_DOWN: 1.15, SIDEWAYS: 0.85, VOLATILE_NO_TREND: 0.75 },
    DOUBLE_TOP:         { TRENDING_UP: 1.10, TRENDING_DOWN: 0.80, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.80 },
    DOUBLE_BOTTOM:      { TRENDING_UP: 0.80, TRENDING_DOWN: 1.10, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.80 },
    TRIPLE_TOP:         { TRENDING_UP: 1.15, TRENDING_DOWN: 0.75, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.75 },
    TRIPLE_BOTTOM:      { TRENDING_UP: 0.75, TRENDING_DOWN: 1.15, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.75 },
    CUP_HANDLE:         { TRENDING_UP: 1.10, TRENDING_DOWN: 0.70, SIDEWAYS: 0.85, VOLATILE_NO_TREND: 0.70 },
    ASC_TRIANGLE:       { TRENDING_UP: 1.10, TRENDING_DOWN: 0.85, SIDEWAYS: 1.10, VOLATILE_NO_TREND: 0.85 },
    DESC_TRIANGLE:      { TRENDING_UP: 0.85, TRENDING_DOWN: 1.10, SIDEWAYS: 1.10, VOLATILE_NO_TREND: 0.85 },
    SYM_TRIANGLE:       { TRENDING_UP: 0.90, TRENDING_DOWN: 0.90, SIDEWAYS: 1.15, VOLATILE_NO_TREND: 0.80 },
    FALLING_WEDGE:      { TRENDING_UP: 0.85, TRENDING_DOWN: 1.10, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.85 },
    RISING_WEDGE:       { TRENDING_UP: 1.10, TRENDING_DOWN: 0.85, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.85 },
    BULL_FLAG:          { TRENDING_UP: 1.15, TRENDING_DOWN: 0.70, SIDEWAYS: 0.75, VOLATILE_NO_TREND: 0.75 },
    BEAR_FLAG:          { TRENDING_UP: 0.70, TRENDING_DOWN: 1.15, SIDEWAYS: 0.75, VOLATILE_NO_TREND: 0.75 },
    BULL_PENNANT:       { TRENDING_UP: 1.15, TRENDING_DOWN: 0.70, SIDEWAYS: 0.80, VOLATILE_NO_TREND: 0.75 },
    BEAR_PENNANT:       { TRENDING_UP: 0.70, TRENDING_DOWN: 1.15, SIDEWAYS: 0.80, VOLATILE_NO_TREND: 0.75 },
    RECT_TOP:           { TRENDING_UP: 0.90, TRENDING_DOWN: 0.90, SIDEWAYS: 1.15, VOLATILE_NO_TREND: 0.85 },
    RECT_BOTTOM:        { TRENDING_UP: 0.90, TRENDING_DOWN: 0.90, SIDEWAYS: 1.15, VOLATILE_NO_TREND: 0.85 },
    VOL_BREAKOUT:       { TRENDING_UP: 1.10, TRENDING_DOWN: 0.90, SIDEWAYS: 1.00, VOLATILE_NO_TREND: 0.90 },
    SUPPORT_BREAK:      { TRENDING_UP: 0.90, TRENDING_DOWN: 1.10, SIDEWAYS: 1.00, VOLATILE_NO_TREND: 0.90 },
    RESISTANCE_BREAK:   { TRENDING_UP: 1.10, TRENDING_DOWN: 0.90, SIDEWAYS: 1.00, VOLATILE_NO_TREND: 0.90 },
    GOLDEN_CROSS:       { TRENDING_UP: 1.00, TRENDING_DOWN: 0.85, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.75 },
    DEATH_CROSS:        { TRENDING_UP: 0.85, TRENDING_DOWN: 1.00, SIDEWAYS: 0.90, VOLATILE_NO_TREND: 0.75 },
  };

  function getRegimeMultiplier(patternKey, regime) {
    const row = REGIME_MULTIPLIERS[patternKey];
    if (!row) return 1.0;
    const val = row[regime];
    return val != null ? Math.max(0.7, Math.min(1.15, val)) : 1.0;
  }

  window.classifyRegime = classifyRegime;
  window.getRegimeMultiplier = getRegimeMultiplier;
  window.REGIMES = REGIMES;
})();
