/**
 * PIFF 3.0 Player Prop Loader
 *
 * Reads today's PIFF 3.0 pick files and exposes props by team abbreviation.
 * Used by Grok prompt builder to inject data-driven player prop analysis.
 * PIFF 3.0: Direction-agnostic (overs + unders), DVP primary filter, H2H, tiers.
 */

import fs from 'fs';
import path from 'path';
import { getCurrentEtDateKey } from '../lib/league-windows';

const PICKS_DIR = '/home/administrator/.openclaw/agents/sportsclaw/workspace/picks';

export interface PiffLeg {
  name: string;
  team: string;
  stat: string;
  line: number;
  edge: number;
  prob: number;
  direction?: string;     // 'over' or 'under' (3.0)
  tier?: number;          // 1=LOCK, 2=STRONG, 3=SOLID (3.0)
  tier_label?: string;    // T1_LOCK, T2_STRONG, T3_SOLID (3.0)
  dvp_adj?: number;
  dvp_rank?: number;
  dvp_tier?: string;      // EASY, AVG, ELITE (3.0)
  dvp?: number;
  h2h_games?: number;     // games vs opponent (3.0)
  h2h_hr?: number;        // HR vs opponent (3.0)
  h2h_flag?: string;      // BOOST or FLAG (3.0)
  opponent?: string;
  is_home?: boolean;
  szn_hr?: number;
  l5_hr?: number;
  l10_hr?: number;
  gap?: number;           // gap from line (3.0)
  league?: string;        // soccer legs have this
}

export interface PiffFile {
  date: string;
  legs?: PiffLeg[];
  main_card?: { legs?: PiffLeg[] };
  borderline_card?: { legs?: PiffLeg[] };
  ranked_board?: { legs?: PiffLeg[] };
  diversified_board?: { legs?: PiffLeg[] };
  playable_ladder?: { legs?: PiffLeg[] };
  watchlist?: { legs?: PiffLeg[] };
}

const NESTED_PIFF_BOARDS = [
  'main_card',
  'borderline_card',
  'ranked_board',
  'diversified_board',
  'playable_ladder',
  'watchlist',
] as const;

export function extractPiffLegs(data: PiffFile): PiffLeg[] {
  const seen = new Set<string>();
  const all: PiffLeg[] = [];

  const append = (legs?: PiffLeg[]) => {
    for (const leg of legs || []) {
      if (leg.edge == null || 'failed' in leg) continue;
      const key = `${leg.name}:${leg.team}:${leg.stat}:${leg.direction || ''}`;
      if (seen.has(key)) continue;
      seen.add(key);
      all.push(leg);
    }
  };

  append(data.legs);
  for (const boardName of NESTED_PIFF_BOARDS) {
    append(data[boardName]?.legs);
  }

  return all;
}

/** Load and parse a PIFF JSON file, returns empty array on failure.
 *  Collects legs from top-level + all nested boards (main_card, watchlist, etc.)
 *  to avoid missing picks that only appear in sub-boards. */
function loadPiffFile(filePath: string): PiffLeg[] {
  try {
    if (!fs.existsSync(filePath)) return [];
    const raw = fs.readFileSync(filePath, 'utf-8');
    const data: PiffFile = JSON.parse(raw);
    return extractPiffLegs(data);
  } catch (err) {
    console.error(`Failed to load PIFF file ${filePath}:`, err);
    return [];
  }
}

/** All leagues that the unified PIFF 3.0 engine supports */
const PIFF_LEAGUES = [
  'nba', 'ncaab', 'nhl', 'mlb',
  'epl', 'la_liga', 'bundesliga', 'serie_a', 'ligue_1', 'champions_league',
];

const piffCache = new Map<string, Record<string, PiffLeg[]>>();

/**
 * Load all PIFF 3.0 props for an ET date, indexed by uppercase team abbreviation.
 * Scans piff30_{league}_{date}.json for every configured league.
 * Falls back to legacy piff30_{date}.json (NBA-only) and piff27 files.
 * Returns: { "ATL": [leg, leg, ...], "LAL": [leg, ...], ... }
 */
export function loadPiffPropsForDate(date: string = getCurrentEtDateKey()): Record<string, PiffLeg[]> {
  if (piffCache.has(date)) return piffCache.get(date)!;

  const map: Record<string, PiffLeg[]> = {};
  let totalLegs = 0;

  // Load unified PIFF 3.0 files for all leagues: piff30_{league}_{date}.json
  // Key format: "league:TEAM" to prevent cross-sport contamination (e.g. DAL Stars vs DAL Mavericks)
  for (const league of PIFF_LEAGUES) {
    const legs = loadPiffFile(path.join(PICKS_DIR, `piff30_${league}_${date}.json`));
    for (const leg of legs) {
      const key = `${league}:${leg.team.toUpperCase()}`;
      if (!map[key]) map[key] = [];
      map[key].push(leg);
      totalLegs++;
    }
  }

  // Fallback: legacy NBA-only file (piff30_{date}.json without league prefix)
  if (!map['nba:ATL'] && !map['nba:LAL']) {
    const legacyNba = loadPiffFile(path.join(PICKS_DIR, `piff30_${date}.json`));
    for (const leg of legacyNba) {
      const key = `nba:${leg.team.toUpperCase()}`;
      if (!map[key]) map[key] = [];
      map[key].push(leg);
      totalLegs++;
    }
  }

  // Fallback: legacy piff27 files for NHL/Soccer
  if (totalLegs === 0) {
    for (const [suffix] of [['nhl'], ['soccer']]) {
      const legs = loadPiffFile(path.join(PICKS_DIR, `piff27_${suffix}_${date}.json`));
      for (const leg of legs) {
        const fallbackLeague = suffix === 'soccer' ? (leg.league || 'soccer') : suffix;
        const key = `${fallbackLeague}:${leg.team.toUpperCase()}`;
        if (!map[key]) map[key] = [];
        map[key].push(leg);
        totalLegs++;
      }
    }
  }

  console.log(`PIFF 3.0: Loaded ${totalLegs} props across ${Object.keys(map).length} teams for ${date}`);
  piffCache.set(date, map);
  return map;
}

export function loadTodaysPiffProps(): Record<string, PiffLeg[]> {
  return loadPiffPropsForDate(getCurrentEtDateKey());
}

/**
 * Get PIFF props relevant to a specific game by matching team abbreviations.
 * Tries both exact and common alias matches.
 */
export function getPiffPropsForGame(
  homeShort: string,
  awayShort: string,
  piffMap?: Record<string, PiffLeg[]>,
  league?: string
): PiffLeg[] {
  const map = piffMap || loadTodaysPiffProps();
  const lg = league || 'nba';
  const homeKey = `${lg}:${homeShort.toUpperCase()}`;
  const awayKey = `${lg}:${awayShort.toUpperCase()}`;

  const homeProps = map[homeKey] || [];
  const awayProps = map[awayKey] || [];

  return [...homeProps, ...awayProps];
}

/**
 * Format PIFF props into a prompt section for Grok.
 */
export function formatPiffForPrompt(props: PiffLeg[]): string {
  if (props.length === 0) return '';

  const lines = props.map(p => {
    const edgePct = (p.edge * 100).toFixed(1);
    const hrPct = p.szn_hr ? (p.szn_hr * 100).toFixed(0) : '?';
    const dir = p.direction ? p.direction.charAt(0).toUpperCase() : 'O';
    const tierStr = p.tier_label ? ` [${p.tier_label}]` : '';
    const dvpStr = p.dvp_tier ? ` DVP: ${p.dvp_tier}` : '';
    const h2hStr = p.h2h_games && p.h2h_games >= 3 ? ` H2H: ${((p.h2h_hr ?? 0) * 100).toFixed(0)}%(${p.h2h_games}g)` : '';
    const gapStr = p.gap ? ` gap:${p.gap.toFixed(1)}` : '';
    return `- ${p.name} ${dir}${p.line} ${p.stat}${tierStr} (HR:${hrPct}%${gapStr}, edge:+${edgePct}%${dvpStr}${h2hStr})`;
  });

  return `\nRAIN MAN PROP INTEL (direction-agnostic, CLV-tracked, 78% hit rate):\n${lines.join('\n')}\nInclude these in your prop_highlights with their tier, direction, and edge percentages.`;
}
