import { normalizePlayerPropMarketStat } from './player-prop-market-registry';

function toNumber(value: any): number | null {
  if (value == null || value === '') return null;
  const parsed = Number(value);
  return Number.isFinite(parsed) ? parsed : null;
}

function normalizeStatKey(value: string | null | undefined): string {
  return String(value || '').trim().toLowerCase().replace(/[\s-]+/g, '_');
}

function normalizeMlbTrackedStat(value: string | null | undefined): string {
  const normalized = normalizeStatKey(value);

  if (['pitching_hits', 'hitsallowed', 'hitallowed'].includes(normalized)) return 'pitching_hits';
  if (['pitching_strikeouts', 'strikeouts', 'strikeout'].includes(normalized)) return 'pitching_strikeouts';
  if ([
    'pitching_basesonballs',
    'pitching_walks',
    'pitchingwalks',
    'walksallowed',
    'walkallowed',
    'walks',
  ].includes(normalized)) return 'pitching_basesonballs';
  if (['pitching_outs', 'outsrecorded', 'outs'].includes(normalized)) return 'pitching_outs';
  if (['pitching_earnedruns', 'earnedruns', 'earnedrun'].includes(normalized)) return 'pitching_earnedruns';
  if (['batting_rbi', 'rbi', 'rbis'].includes(normalized)) return 'batting_rbi';
  if (['batting_basesonballs', 'batting_walks', 'battingwalks', 'walk', 'walks'].includes(normalized)) return 'batting_basesonballs';
  if (['batting_homeruns', 'homerun', 'homeruns', 'home_run', 'home_runs'].includes(normalized)) return 'batting_homeruns';
  if (['batting_hits', 'hit', 'hits'].includes(normalized)) return 'batting_hits';
  if (['batting_runs', 'run', 'runs', 'point', 'points'].includes(normalized)) return 'batting_runs';

  return normalized;
}

export function normalizeClvPropStat(stat: string | null | undefined, league?: string | null): string {
  const raw = (stat || '').trim();
  if (!raw) return '';

  const safeLeague = (league || '').trim().toLowerCase();
  const canonical = normalizePlayerPropMarketStat(safeLeague, raw) || raw;
  const normalized = canonical.toLowerCase().replace(/[\s-]+/g, '_');

  if (safeLeague === 'nhl') {
    if (['shots_ongoal', 'shots_on_goal', 'sog'].includes(normalized)) return 'shots';
    if (['goalie_saves', 'saves', 'save'].includes(normalized)) return 'saves';
  }

  if (['threes', 'three_pointers_made', 'threepointersmade'].includes(normalized)) {
    return 'threePointersMade';
  }

  if (safeLeague === 'mlb' && ['batting_runs', 'run', 'runs', 'point', 'points'].includes(normalized)) {
    return 'runs';
  }

  return canonical;
}

export interface PlayerPropClvFitInput {
  league?: string | null;
  statType?: string | null;
  normalizedStatType?: string | null;
  recommendation?: string | null;
  projectedProbability?: number | null;
  confidenceFactor?: number | null;
  odds?: number | null;
  marketLine?: number | null;
}

export interface PlayerPropClvFitProfile {
  normalizedStat: string | null;
  eligible: boolean;
  fitScore: number;
  fitLabel: 'TRACKED' | 'CAUTION';
}

export function assessPlayerPropClvFit(input: PlayerPropClvFitInput): PlayerPropClvFitProfile {
  const league = (input.league || '').toLowerCase();
  const normalizedStat = normalizeClvPropStat(
    input.normalizedStatType || input.statType || null,
    league,
  ) || null;
  const direction = String(input.recommendation || '').trim().toLowerCase();
  const probability = toNumber(input.projectedProbability);
  const confidenceFactor = toNumber(input.confidenceFactor);
  const odds = toNumber(input.odds);
  const marketLine = toNumber(input.marketLine);
  const effectiveConfidence = confidenceFactor != null
    ? (confidenceFactor <= 1 ? confidenceFactor * 100 : confidenceFactor)
    : probability;

  let eligible = true;
  if (normalizedStat && (direction === 'over' || direction === 'under')) {
    const stat = normalizedStat.toLowerCase();
    if (['shots', 'saves', 'rebounds'].includes(stat) && direction === 'over') eligible = false;
    if (stat === 'assists' && direction === 'over') eligible = false;
    if (stat === 'goals' && direction === 'over') eligible = false;
    if (league === 'nba' && direction === 'over' && effectiveConfidence != null && effectiveConfidence < 65) {
      eligible = false;
    }
  }

  if (league === 'mlb' && normalizedStat && (direction === 'over' || direction === 'under')) {
    const stat = normalizeMlbTrackedStat(normalizedStat);

    if (direction !== 'under') {
      eligible = false;
    } else if (odds != null && odds > 110) {
      eligible = false;
    } else {
      // MLB tracked props are pitcher-under only with stat-specific line guards.
      // Broad hitter exposure and the low-line pitcher buckets backtested poorly.
      eligible = (() => {
        switch (stat) {
          case 'pitching_strikeouts':
            return marketLine != null && marketLine >= 4.5;
          case 'pitching_hits':
            return marketLine != null && marketLine >= 4.5;
          case 'pitching_basesonballs':
            return marketLine === 1.5;
          case 'pitching_earnedruns':
            return marketLine != null && marketLine >= 2.5;
          case 'pitching_outs':
            return marketLine != null;
          default:
            return false;
        }
      })();
    }
  }

  const confidenceBonus = effectiveConfidence == null
    ? 0
    : Math.max(0, Math.min(15, (effectiveConfidence - 60) / 2));
  const fitScore = Math.round((eligible ? 72 : 28) + confidenceBonus);

  return {
    normalizedStat,
    eligible,
    fitScore,
    fitLabel: eligible ? 'TRACKED' : 'CAUTION',
  };
}
