export type ForecastAssetType =
  | 'GAME_MARKETS'
  | 'GAME_TOTAL'
  | 'TEAM_PROPS'
  | 'PLAYER_PROP'
  | 'MLB_F5'
  | 'MLB_F5_SIDE'
  | 'MLB_F5_TOTAL'
  | 'MLB_RUN_LINE'
  | 'TEAM_TOTAL';

export type ForecastMarketOrigin = 'bundle' | 'source_backed' | 'modeled' | 'inferred';
export type ForecastPlayerRole = 'batter' | 'pitcher' | 'unknown' | null;

export interface ForecastAssetDescriptor {
  assetType: string;
  assetLabel: string;
  marketFamily: string;
  marketOrigin: ForecastMarketOrigin;
  sourceBacked: boolean;
  legacyBundle: boolean;
  playerRole: ForecastPlayerRole;
}

const BATTER_STAT_TYPES = new Set([
  'hits',
  'singles',
  'doubles',
  'triples',
  'homeruns',
  'home_runs',
  'rbi',
  'hits+runs+rbi',
  'walks',
  'basesonballs',
  'stolenbases',
  'totalbases',
  'fantasyscore',
  'points',
  'batting_hits',
  'batting_singles',
  'batting_doubles',
  'batting_triples',
  'batting_homeruns',
  'batting_rbi',
  'batting_hits+runs+rbi',
  'batting_basesonballs',
  'batting_stolenbases',
  'batting_strikeouts',
  'batting_totalbases',
]);

const PITCHER_STAT_TYPES = new Set([
  'pitching_strikeouts',
  'pitching_basesonballs',
  'pitching_hits',
  'pitching_earnedruns',
  'pitching_outs',
  'walks_allowed',
  'hits_allowed',
  'earned_runs',
  'outs_recorded',
]);

function toInt(value: any): number {
  const n = Number(value || 0);
  return Number.isFinite(n) ? n : 0;
}

export function getMlbPlayerRole(statType?: string | null): ForecastPlayerRole {
  if (!statType) return null;
  const normalized = String(statType).replace(/\s+/g, '').toLowerCase();
  if (normalized.startsWith('pitching_')) return 'pitcher';
  if (normalized.startsWith('batting_')) return 'batter';
  if (PITCHER_STAT_TYPES.has(normalized)) return 'pitcher';
  if (BATTER_STAT_TYPES.has(normalized)) return 'batter';
  return 'unknown';
}

export function describeForecastAsset(
  forecastType: string,
  payload?: any,
): ForecastAssetDescriptor {
  if (forecastType === 'GAME_TOTAL') {
    return {
      assetType: forecastType,
      assetLabel: 'Game Total',
      marketFamily: 'game_total',
      marketOrigin: 'source_backed',
      sourceBacked: true,
      legacyBundle: false,
      playerRole: null,
    };
  }

  if (forecastType === 'MLB_RUN_LINE') {
    return {
      assetType: forecastType,
      assetLabel: 'Run Line',
      marketFamily: 'run_line',
      marketOrigin: 'source_backed',
      sourceBacked: true,
      legacyBundle: false,
      playerRole: null,
    };
  }

  if (forecastType === 'MLB_F5_SIDE') {
    return {
      assetType: forecastType,
      assetLabel: 'First 5 Side',
      marketFamily: 'f5_side',
      marketOrigin: 'modeled',
      sourceBacked: false,
      legacyBundle: false,
      playerRole: null,
    };
  }

  if (forecastType === 'MLB_F5_TOTAL') {
    return {
      assetType: forecastType,
      assetLabel: 'First 5 Total',
      marketFamily: 'f5_total',
      marketOrigin: 'modeled',
      sourceBacked: false,
      legacyBundle: false,
      playerRole: null,
    };
  }

  if (forecastType === 'MLB_F5') {
    return {
      assetType: forecastType,
      assetLabel: 'First 5 Bundle',
      marketFamily: 'f5_bundle',
      marketOrigin: 'modeled',
      sourceBacked: false,
      legacyBundle: true,
      playerRole: null,
    };
  }

  if (forecastType === 'TEAM_TOTAL') {
    return {
      assetType: forecastType,
      assetLabel: 'Team Total',
      marketFamily: 'team_total',
      marketOrigin: 'inferred',
      sourceBacked: false,
      legacyBundle: false,
      playerRole: null,
    };
  }

  if (forecastType === 'TEAM_PROPS') {
    return {
      assetType: forecastType,
      assetLabel: 'Team Props Bundle',
      marketFamily: 'team_props_bundle',
      marketOrigin: 'bundle',
      sourceBacked: true,
      legacyBundle: true,
      playerRole: null,
    };
  }

  if (forecastType === 'PLAYER_PROP') {
    const explicitRole = payload?.player_role || payload?.playerRole || null;
    const playerRole =
      explicitRole === 'batter' || explicitRole === 'pitcher'
        ? explicitRole
        : getMlbPlayerRole(
            payload?.normalized_stat_type ||
            payload?.normalizedStatType ||
            payload?.stat_type ||
            payload?.statType ||
            null,
          );
    return {
      assetType: forecastType,
      assetLabel: playerRole === 'pitcher' ? 'Pitcher Prop' : playerRole === 'batter' ? 'Batter Prop' : 'Player Prop',
      marketFamily: playerRole === 'pitcher' ? 'pitcher_props' : playerRole === 'batter' ? 'batter_props' : 'player_props',
      marketOrigin: 'source_backed',
      sourceBacked: true,
      legacyBundle: false,
      playerRole,
    };
  }

  return {
    assetType: forecastType,
    assetLabel: forecastType === 'GAME_MARKETS' ? 'Game Markets Bundle' : forecastType,
    marketFamily: forecastType === 'GAME_MARKETS' ? 'game_bundle' : 'other',
    marketOrigin: forecastType === 'GAME_MARKETS' ? 'bundle' : 'source_backed',
    sourceBacked: forecastType !== 'GAME_MARKETS' ? true : true,
    legacyBundle: forecastType === 'GAME_MARKETS',
    playerRole: null,
  };
}

export function summarizeForecastCountRows(
  rows: Array<{ forecast_type?: string; count?: number; total?: number }>,
): { byType: Record<string, number>; byFamily: Record<string, number>; total: number } {
  const byType: Record<string, number> = {};
  const byFamily: Record<string, number> = {};
  let total = 0;

  for (const row of rows) {
    const forecastType = String(row.forecast_type || '');
    const count = toInt(row.count ?? row.total);
    if (!forecastType || count <= 0) continue;

    byType[forecastType] = (byType[forecastType] || 0) + count;
    const descriptor = describeForecastAsset(forecastType);
    byFamily[descriptor.marketFamily] = (byFamily[descriptor.marketFamily] || 0) + count;
    total += count;
  }

  return { byType, byFamily, total };
}
