const axios = require('axios');

const WEATHER_GOV_BASE = 'https://api.weather.gov';
const OPEN_METEO_BASE = 'https://api.open-meteo.com/v1/forecast';

function classifyLineMove(movement, hoursFromOpen) {
  if (Math.abs(movement) < 0.5) return null;
  if (hoursFromOpen < 2) return 'sharp';
  return 'public';
}

async function checkWeather(parkCoords, timeout = 3000) {
  const [lat, lon] = parkCoords;

  // Try api.weather.gov first
  try {
    const pointRes = await axios.get(
      `${WEATHER_GOV_BASE}/points/${lat},${lon}`,
      { timeout, headers: { 'User-Agent': 'VYNDR/1.0' } }
    );
    const forecastUrl = pointRes.data.properties.forecastHourly;
    const forecastRes = await axios.get(forecastUrl, {
      timeout,
      headers: { 'User-Agent': 'VYNDR/1.0' },
    });
    const period = forecastRes.data.properties.periods[0];
    return {
      wind_speed: parseInt(period.windSpeed) || 0,
      wind_direction: period.windDirection || 'N',
      temp: period.temperature || 72,
      humidity: period.relativeHumidity ? period.relativeHumidity.value : 50,
      rain_probability: period.probabilityOfPrecipitation ? period.probabilityOfPrecipitation.value : 0,
    };
  } catch (_err) {
    // Fallback to open-meteo
    try {
      const res = await axios.get(OPEN_METEO_BASE, {
        params: {
          latitude: lat,
          longitude: lon,
          hourly: 'temperature_2m,relative_humidity_2m,wind_speed_10m,wind_direction_10m,precipitation_probability',
          forecast_days: 1,
          temperature_unit: 'fahrenheit',
          wind_speed_unit: 'mph',
        },
        timeout: 5000,
      });
      const hourly = res.data.hourly;
      const idx = new Date().getHours();
      return {
        wind_speed: hourly.wind_speed_10m[idx] || 0,
        wind_direction: degreesToCardinal(hourly.wind_direction_10m[idx] || 0),
        temp: hourly.temperature_2m[idx] || 72,
        humidity: hourly.relative_humidity_2m[idx] || 50,
        rain_probability: hourly.precipitation_probability[idx] || 0,
      };
    } catch (_fallbackErr) {
      return {
        wind_speed: 0,
        wind_direction: 'N',
        temp: 72,
        humidity: 50,
        rain_probability: 0,
      };
    }
  }
}

function degreesToCardinal(deg) {
  const dirs = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
  return dirs[Math.round(deg / 45) % 8];
}

function evaluateMlbKillConditions(context) {
  const {
    inLineup,
    pitcherScratched,
    weather,
    platoonDelta,
    paVsHandedness,
    lineMovement,
    hoursFromOpen,
    parkFactor,
    rainProbability,
    onInjuryReport,
  } = context;

  const conditions = [];

  // 1. LINEUP_OUT
  if (inLineup === false) {
    conditions.push({
      code: 'LINEUP_OUT',
      reason: 'Player not in confirmed lineup',
    });
  }

  // 2. PITCHER_SCRATCH
  if (pitcherScratched === true) {
    conditions.push({
      code: 'PITCHER_SCRATCH',
      reason: 'Starting pitcher has been scratched',
    });
  }

  // 3. WIND_IN
  if (weather && weather.wind_speed >= 15 && weather.wind_direction === 'IN') {
    conditions.push({
      code: 'WIND_IN',
      reason: `Wind blowing in at ${weather.wind_speed} mph — suppresses power`,
    });
  }

  // 4. PLATOON_DISADVANTAGE
  if (platoonDelta != null && platoonDelta > 12) {
    conditions.push({
      code: 'PLATOON_DISADVANTAGE',
      reason: `Platoon split delta of ${platoonDelta}% exceeds 12% threshold`,
    });
  }

  // 5. SMALL_SAMPLE
  if (paVsHandedness != null && paVsHandedness < 50) {
    conditions.push({
      code: 'SMALL_SAMPLE',
      reason: `Only ${paVsHandedness} PA vs current handedness`,
    });
  }

  // 6. LINE_MOVE_AGAINST
  if (lineMovement != null && Math.abs(lineMovement) >= 0.5) {
    const moveType = classifyLineMove(lineMovement, hoursFromOpen || 0);
    conditions.push({
      code: 'LINE_MOVE_AGAINST',
      reason: `Line moved ${lineMovement > 0 ? '+' : ''}${lineMovement} (${moveType} money)`,
    });
  }

  // 7. PARK_SUPPRESSOR
  if (parkFactor != null && parkFactor < 0.90) {
    conditions.push({
      code: 'PARK_SUPPRESSOR',
      reason: `Park factor ${parkFactor} below 0.90 threshold`,
    });
  }

  // 8. WEATHER_RAIN
  if (rainProbability != null && rainProbability > 50) {
    conditions.push({
      code: 'WEATHER_RAIN',
      reason: `Rain probability at ${rainProbability}%`,
    });
  }

  // 9. INJURY_REPORT
  if (onInjuryReport === true) {
    conditions.push({
      code: 'INJURY_REPORT',
      reason: 'Player appears on injury report',
    });
  }

  // 10. HUMIDITY_SUPPRESSOR
  if (weather && weather.humidity > 80 && weather.temp < 60) {
    conditions.push({
      code: 'HUMIDITY_SUPPRESSOR',
      reason: `Humidity ${weather.humidity}% with temp ${weather.temp}F — suppresses ball flight`,
    });
  }

  return conditions;
}

module.exports = { evaluateMlbKillConditions, classifyLineMove, checkWeather };
