/**
 * home-field-scout.ts — Home Field Scout agent for HCW insight generation.
 *
 * For indoor sports (NBA, NHL, NCAAB): home crowd + matchup context analysis.
 * For outdoor sports (NFL, MLB, soccer): weather + home field context analysis.
 *
 * Uses callLLM (Claude → Grok fallback) with structured JSON output.
 * Enhanced with Narrative Engine signal enrichment rules.
 */

import pool from '../db';
import { getVenue, isIndoorGame, isHighAltitude, VenueInfo } from './venue';
import { fetchGameWeather, GameWeather } from './weather';
import { getHcwEnrichmentPrompt, editorialGuardrails } from './narrative-engine';

// ── LLM call (imported inline to avoid circular deps) ──
const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY || '';
const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';
const CLAUDE_MODEL = 'anthropic/claude-opus-4-6';
const GROK_API_KEY = process.env.GROK_API_KEY || '';
const GROK_API_URL = process.env.GROK_API_URL || 'https://api.x.ai/v1/chat/completions';
const GROK_MODEL = process.env.GROK_MODEL || 'grok-4-1-fast-reasoning';

function trackUsage(params: Record<string, any>) {
  pool.query(
    `INSERT INTO rm_api_usage (category, subcategory, event_id, league, provider, model, input_tokens, output_tokens, total_tokens, response_time_ms, success, error_message, metadata)
     VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)`,
    [params.category, params.subcategory || null, params.eventId || null, params.league || null,
     params.provider, params.model, params.inputTokens, params.outputTokens, params.totalTokens,
     params.responseTimeMs, params.success, params.errorMessage || null,
     JSON.stringify(params.metadata || {})]
  ).catch(err => console.error('[api-usage] HCW track error:', err.message));
}

async function callHcwLLM(systemPrompt: string, userPrompt: string, league?: string, eventId?: string): Promise<string> {
  const context = { category: 'insight', subcategory: 'hcw', league, eventId };
  const maxTokens = 3000;
  const temperature = 0.6;
  const timeoutMs = 60000;

  // Try Claude first
  if (OPENROUTER_API_KEY) {
    try {
      const startMs = Date.now();
      const res = await fetch(OPENROUTER_API_URL, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${OPENROUTER_API_KEY}`,
          'Content-Type': 'application/json',
          'HTTP-Referer': 'https://rainmakersports.app',
          'X-Title': 'Rainmaker Sports',
        },
        body: JSON.stringify({
          model: CLAUDE_MODEL,
          messages: [{ role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }],
          temperature, max_tokens: maxTokens,
        }),
        signal: AbortSignal.timeout(timeoutMs),
      });
      const responseTimeMs = Date.now() - startMs;
      if (!res.ok) throw new Error(`Claude ${res.status}`);
      const data = await res.json() as any;
      let content = data.choices?.[0]?.message?.content || '';
      content = content.replace(/```json\s*/g, '').replace(/```\s*/g, '').trim();
      if (!content) throw new Error('Claude returned empty');
      const usage = data.usage || {};
      trackUsage({ ...context, provider: 'claude', model: CLAUDE_MODEL, inputTokens: usage.prompt_tokens || 0, outputTokens: usage.completion_tokens || 0, totalTokens: usage.total_tokens || 0, responseTimeMs, success: true });
      return content;
    } catch (err) {
      console.warn('[hcw] Claude failed, falling back to Grok:', (err as Error).message);
    }
  }

  // Fallback: Grok
  const startMs = Date.now();
  const res = await fetch(GROK_API_URL, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${GROK_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: GROK_MODEL,
      messages: [{ role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }],
      temperature, max_tokens: maxTokens,
    }),
    signal: AbortSignal.timeout(timeoutMs),
  });
  const responseTimeMs = Date.now() - startMs;
  if (!res.ok) {
    trackUsage({ ...context, provider: 'grok', model: GROK_MODEL, inputTokens: 0, outputTokens: 0, totalTokens: 0, responseTimeMs, success: false, errorMessage: `Grok ${res.status}` });
    throw new Error(`All LLM providers failed for HCW`);
  }
  const data = await res.json() as any;
  let content = data.choices?.[0]?.message?.content || '';
  content = content.replace(/```json\s*/g, '').replace(/```\s*/g, '').trim();
  const usage = data.usage || {};
  trackUsage({ ...context, provider: 'grok', model: GROK_MODEL, inputTokens: usage.prompt_tokens || 0, outputTokens: usage.completion_tokens || 0, totalTokens: usage.total_tokens || 0, responseTimeMs, success: true });
  return content;
}

// ── Result Types ──

export interface HcwInsightResult {
  title: string;
  venue: string;
  city: string;
  indoor: boolean;
  weather: {
    temperature: string;
    wind: string;
    conditions: string;
    precipitation: string;
    alerts: string[];
  } | null;                     // null for indoor venues
  home_edge: string;            // 2-3 sentence home field advantage analysis
  crowd_factor: string;         // crowd energy/capacity analysis
  key_factors: string[];        // 3-5 bullet points
  impact_rating: 'HIGH' | 'MEDIUM' | 'LOW';
  altitude_note: string | null; // only for high-altitude venues
}

// ── Main Generation Function ──

export async function generateHcwInsight(context: {
  homeTeam: string;
  awayTeam: string;
  homeShort: string;
  awayShort: string;
  league: string;
  startsAt: string;
  forecastSummary?: string;
  eventId?: string;
}): Promise<HcwInsightResult> {
  const indoor = isIndoorGame(context.homeShort, context.league);
  const venue = getVenue(context.homeShort, context.league);
  const highAlt = isHighAltitude(context.homeShort, context.league);

  // Fetch weather for outdoor venues
  let weather: GameWeather | null = null;
  if (!indoor && venue) {
    weather = await fetchGameWeather(venue.lat, venue.lon, context.startsAt);
  }

  const systemPrompt = `You are the Home Field Scout, a specialized Rainmaker agent that analyzes home field advantage, venue conditions, and environmental factors for sports games. You provide concise, data-driven analysis. Return valid JSON only.

LANGUAGE RULES: Use "market" not "betting market". Use "market speculators" not "bettors". Never use "lock", "guarantee", or "sure thing". Use "Rain Man" only once — after that, say "the model", "the forecast", "the signal", or "RM".
${getHcwEnrichmentPrompt()}`;

  const userPrompt = buildHcwPrompt(context, venue, indoor, weather, highAlt);

  for (let attempt = 0; attempt < 2; attempt++) {
    try {
      const content = await callHcwLLM(systemPrompt, userPrompt, context.league, context.eventId);
      const parsed = JSON.parse(content) as HcwInsightResult;
      if (!parsed.title || !parsed.home_edge) {
        throw new Error('Missing required HCW insight fields');
      }
      // Ensure weather is null for indoor
      if (indoor) parsed.weather = null;
      // Set venue metadata
      parsed.venue = venue?.name || 'Unknown Venue';
      parsed.city = venue?.city || '';
      parsed.indoor = indoor;
      parsed.altitude_note = highAlt ? `${venue?.name || 'Venue'} sits at ${venue?.altitude || 5000}+ feet elevation — affects ball flight, player stamina, and visiting team performance.` : null;
      // ── NARRATIVE ENGINE: Apply editorial guardrails ──
      parsed.home_edge = editorialGuardrails(parsed.home_edge);
      parsed.crowd_factor = editorialGuardrails(parsed.crowd_factor);
      parsed.key_factors = parsed.key_factors.map(f => editorialGuardrails(f));
      return parsed;
    } catch (err) {
      console.error(`[hcw] attempt ${attempt + 1} failed:`, err);
      if (attempt < 1) {
        await new Promise(r => setTimeout(r, 2000));
        continue;
      }
      return getDefaultHcwInsight(context, venue, indoor, weather, highAlt);
    }
  }

  return getDefaultHcwInsight(context, venue, indoor, weather, highAlt);
}

function buildHcwPrompt(
  ctx: { homeTeam: string; awayTeam: string; league: string; startsAt: string; forecastSummary?: string },
  venue: VenueInfo | null,
  indoor: boolean,
  weather: GameWeather | null,
  highAlt: boolean
): string {
  const venueBlock = venue
    ? `VENUE: ${venue.name}, ${venue.city}
Type: ${indoor ? 'Indoor' : 'Outdoor'} (Capacity: ${venue.capacity.toLocaleString()})
Surface: ${venue.surface || 'unknown'}
${highAlt ? `ALTITUDE: ${venue.altitude} feet — HIGH ALTITUDE VENUE` : ''}`
    : `VENUE: Unknown (${indoor ? 'Indoor' : 'Outdoor'} venue assumed based on league)`;

  const weatherBlock = weather && !indoor
    ? `WEATHER CONDITIONS:
Current: ${weather.current.temperature_f}°F (feels like ${weather.current.feels_like_f}°F), ${weather.current.conditions}
Wind: ${weather.current.wind_mph} mph ${weather.current.wind_direction}
Humidity: ${weather.current.humidity}%
${weather.gameTime ? `At Game Time: ${weather.gameTime.temperature_f}°F, ${weather.gameTime.conditions}, Wind: ${weather.gameTime.wind_mph} mph, Precip: ${weather.gameTime.precipitation_chance}%` : ''}
${weather.alerts.length > 0 ? `ALERTS: ${weather.alerts.join(', ')}` : ''}`
    : indoor
    ? 'WEATHER: Indoor venue — controlled climate, no weather impact.'
    : 'WEATHER: Data unavailable.';

  return `Analyze the home field advantage and ${indoor ? 'crowd' : 'weather + venue'} factors for this ${ctx.league.toUpperCase()} game.

MATCHUP: ${ctx.awayTeam} @ ${ctx.homeTeam}
GAME TIME: ${ctx.startsAt}
LEAGUE: ${ctx.league.toUpperCase()}

${venueBlock}
${weatherBlock}

${ctx.forecastSummary ? `FORECAST CONTEXT: ${ctx.forecastSummary}` : ''}

Return ONLY this JSON:
{
  "title": "${indoor ? 'Home Crowd Analysis' : 'Weather + Home Field Report'}: [brief title]",
  "home_edge": "2-3 sentence analysis of ${ctx.homeTeam}'s home field advantage${indoor ? ', crowd energy, and atmosphere' : ', including how weather and venue conditions affect the game'}",
  "crowd_factor": "1-2 sentence analysis of ${indoor ? 'crowd noise, arena atmosphere, and capacity impact' : 'how fans and venue conditions combine to create home advantage'}",
  "key_factors": [
    "factor 1: specific advantage or concern",
    "factor 2: ...",
    "factor 3: ..."
  ],
  "impact_rating": "HIGH/MEDIUM/LOW based on how much these factors affect the outcome"
}

GUIDELINES:
- For ${ctx.league.toUpperCase()}: Consider ${indoor
    ? 'crowd noise levels, arena reputation, home record, altitude if applicable, and travel distance for the away team'
    : 'wind impact on passing/kicking, temperature effects on player performance, precipitation risk, surface conditions, and travel weather'}.
- Be specific about THIS venue and THIS matchup — avoid generic statements.
- impact_rating: HIGH if weather is extreme, venue is notoriously tough, or altitude is a factor. LOW if conditions are neutral. MEDIUM otherwise.`;
}

function getDefaultHcwInsight(
  ctx: { homeTeam: string; awayTeam: string; homeShort: string; league: string },
  venue: VenueInfo | null,
  indoor: boolean,
  weather: GameWeather | null,
  highAlt: boolean
): HcwInsightResult {
  const wx = weather && !indoor ? weather.gameTime || weather.current : null;
  return {
    title: indoor ? `Home Crowd Analysis: ${ctx.homeTeam}` : `Weather + Home Field: ${ctx.homeTeam}`,
    venue: venue?.name || 'Unknown Venue',
    city: venue?.city || '',
    indoor,
    weather: wx ? {
      temperature: `${wx.temperature_f}°F`,
      wind: `${wx.wind_mph} mph ${wx.wind_direction}`,
      conditions: wx.conditions,
      precipitation: `${wx.precipitation_chance}%`,
      alerts: weather?.alerts || [],
    } : null,
    home_edge: `${ctx.homeTeam} plays at ${venue?.name || 'their home venue'} with a capacity of ${venue?.capacity?.toLocaleString() || 'N/A'} fans. Home field advantage analysis is being generated.`,
    crowd_factor: indoor
      ? `${venue?.name || 'The arena'} is known for its atmosphere during ${ctx.league.toUpperCase()} games.`
      : `Conditions at ${venue?.name || 'the venue'} will factor into game strategy.`,
    key_factors: [
      `Home crowd support at ${venue?.name || 'the venue'}`,
      indoor ? 'Arena noise and atmosphere' : `Current conditions: ${wx?.conditions || 'Clear'}`,
      `Travel factor for ${ctx.awayTeam}`,
    ],
    impact_rating: highAlt ? 'HIGH' : 'MEDIUM',
    altitude_note: highAlt ? `${venue?.name || 'Venue'} sits at ${venue?.altitude || 5000}+ feet elevation.` : null,
  };
}

/**
 * Check if HCW data is available for a given league.
 * HCW is available for all leagues — indoor sports get crowd analysis,
 * outdoor sports get weather + home field.
 */
export function hasHcwData(league: string): boolean {
  const supported = ['nba', 'nhl', 'nfl', 'mlb', 'ncaab', 'ncaaf', 'wnba', 'epl', 'la_liga', 'bundesliga', 'serie_a', 'ligue_1', 'champions_league', 'mma'];
  return supported.includes(league.toLowerCase());
}
