/**
 * Grok Function Calling Tools
 *
 * Defines tools that Grok can call during response generation
 * to dynamically fetch data from our APIs.
 */

import * as directQuery from '@/lib/directSportsQuery';
import { getSportsDb } from '@/lib/sportsDb';

// Tool definitions for Grok API
export const GROK_TOOLS = [
  {
    type: 'function',
    function: {
      name: 'get_live_scores',
      description: 'Get live scores for games currently in progress or recently completed. Use this when the user asks about current scores, live games, or game results.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl', 'ncaab', 'ncaaf'],
            description: 'The sports league to get scores for'
          }
        },
        required: ['league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_upcoming_games',
      description: 'Get upcoming games with odds and betting lines. Use this when the user asks about upcoming matchups, schedules, or betting odds.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl', 'ncaab', 'ncaaf'],
            description: 'The sports league'
          },
          team: {
            type: 'string',
            description: 'Optional team name to filter by'
          },
          days: {
            type: 'number',
            description: 'Number of days ahead to look (default: 7)'
          }
        },
        required: ['league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_player_stats',
      description: 'Get player statistics and performance data. Use this when the user asks about player stats, averages, or recent performance.',
      parameters: {
        type: 'object',
        properties: {
          player_name: {
            type: 'string',
            description: 'The player name to look up'
          },
          days: {
            type: 'number',
            description: 'Number of days of recent stats (default: 30)'
          },
          stat_keys: {
            type: 'array',
            items: { type: 'string' },
            description: 'Specific stats to retrieve (e.g., points, rebounds, assists)'
          }
        },
        required: ['player_name']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_player_team',
      description: 'Get what team a player currently plays for. Use this when the user asks which team a player is on.',
      parameters: {
        type: 'object',
        properties: {
          player_name: {
            type: 'string',
            description: 'The player name to look up'
          }
        },
        required: ['player_name']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'run_strategy_backtest',
      description: 'Run a betting strategy backtest to see historical performance. Use this when the user wants to test, simulate, or backtest a betting strategy.',
      parameters: {
        type: 'object',
        properties: {
          strategy: {
            type: 'string',
            enum: ['home favorites', 'away underdogs', 'home underdogs', 'heavy favorites', 'big underdogs', 'overs', 'unders', 'all favorites', 'all underdogs'],
            description: 'The betting strategy to test'
          },
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl', 'ncaab', 'ncaaf'],
            description: 'The sports league'
          },
          season: {
            type: 'number',
            description: 'The season year (e.g., 2026 for 2025-26 season)'
          }
        },
        required: ['strategy', 'league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_team_roster',
      description: 'Get the current roster of players for a team. Use this when the user asks about team rosters or who plays for a team.',
      parameters: {
        type: 'object',
        properties: {
          team: {
            type: 'string',
            description: 'The team name or abbreviation'
          },
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl'],
            description: 'Optional league to narrow search'
          }
        },
        required: ['team']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_standings',
      description: 'Get current league standings and team records. Use this when the user asks about standings, rankings, or team records.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl', 'ncaab', 'ncaaf'],
            description: 'The sports league'
          },
          season: {
            type: 'number',
            description: 'The season year (optional, defaults to current)'
          }
        },
        required: ['league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_player_props',
      description: 'Get player prop betting lines for upcoming games. Use this when the user asks about player props, over/unders for player stats.',
      parameters: {
        type: 'object',
        properties: {
          player: {
            type: 'string',
            description: 'Player name (optional)'
          },
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl'],
            description: 'The sports league'
          },
          team: {
            type: 'string',
            description: 'Team name to filter by (optional)'
          }
        },
        required: ['league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_weather_impact',
      description: 'Get weather data and betting impact analysis for outdoor games. Use this for NFL, MLB, or college football games.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nfl', 'mlb', 'ncaaf'],
            description: 'The outdoor sports league'
          },
          team: {
            type: 'string',
            description: 'Optional team to filter by'
          }
        },
        required: ['league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_injuries',
      description: 'Get current injury reports for a team or league. Use this when the user asks about injuries or player availability.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl'],
            description: 'The sports league'
          },
          team: {
            type: 'string',
            description: 'Optional team to filter by'
          }
        },
        required: ['league']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_betting_trends',
      description: 'Get ATS records and betting trends for teams. Use this when the user asks about betting performance, ATS records, or trends.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl'],
            description: 'The sports league'
          },
          team: {
            type: 'string',
            description: 'Optional team to filter by'
          }
        },
        required: []
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'search_sports',
      description: 'Search for players or teams by name. Use this when you need to find or verify player/team information.',
      parameters: {
        type: 'object',
        properties: {
          query: {
            type: 'string',
            description: 'Search query (player name, team name, etc.)'
          }
        },
        required: ['query']
      }
    }
  },
  {
    type: 'function',
    function: {
      name: 'get_recent_games',
      description: 'Get recent completed games with scores and results. Use this when the user asks about past games or recent results.',
      parameters: {
        type: 'object',
        properties: {
          league: {
            type: 'string',
            enum: ['nba', 'nfl', 'mlb', 'nhl', 'ncaab', 'ncaaf'],
            description: 'The sports league'
          },
          team: {
            type: 'string',
            description: 'Optional team to filter by'
          },
          days: {
            type: 'number',
            description: 'Number of days to look back (default: 7)'
          }
        },
        required: ['league']
      }
    }
  }
];

/**
 * Execute a tool call from Grok
 */
export async function executeToolCall(
  toolName: string,
  args: Record<string, any>
): Promise<string> {
  try {
    switch (toolName) {
      case 'get_live_scores': {
        const scores = await directQuery.fetchLiveScoresFromApi(args.league);
        if (scores && scores.games.length > 0) {
          return JSON.stringify({
            success: true,
            source: 'ESPN',
            fetchedAt: scores.fetchedAt,
            games: scores.games.map(g => ({
              matchup: `${g.awayTeam} @ ${g.homeTeam}`,
              score: g.homeScore !== undefined ? `${g.awayScore} - ${g.homeScore}` : 'Not started',
              status: g.status,
              period: g.period,
              clock: g.clock
            }))
          });
        }
        return JSON.stringify({ success: false, message: 'No live games found' });
      }

      case 'get_upcoming_games': {
        const games = await directQuery.getUpcomingGames({
          league: args.league,
          team: args.team,
          days: args.days || 7
        });
        return JSON.stringify({
          success: true,
          count: games.length,
          games: games.slice(0, 10).map(g => ({
            date: g.date,
            matchup: `${g.awayTeam} @ ${g.homeTeam}`,
            moneyline: g.moneylineHome ? `${g.awayTeam} ${g.moneylineAway > 0 ? '+' : ''}${g.moneylineAway} / ${g.homeTeam} ${g.moneylineHome > 0 ? '+' : ''}${g.moneylineHome}` : 'No odds',
            spread: g.spreadHome ? `${g.homeTeam} ${g.spreadHome > 0 ? '+' : ''}${g.spreadHome}` : null,
            total: g.total || null
          }))
        });
      }

      case 'get_player_stats': {
        const stats = await directQuery.getPlayerStats(args.player_name, {
          days: args.days || 30,
          statKeys: args.stat_keys
        });
        if (stats.length > 0) {
          return JSON.stringify({
            success: true,
            player: args.player_name,
            gamesFound: stats.length,
            recentGames: stats.slice(0, 10)
          });
        }
        return JSON.stringify({ success: false, message: `No stats found for ${args.player_name}` });
      }

      case 'get_player_team': {
        const player = await directQuery.getPlayerTeam(args.player_name);
        if (player) {
          return JSON.stringify({
            success: true,
            player: player.name,
            team: player.team,
            teamFullName: player.teamFullName,
            league: player.league,
            position: player.position
          });
        }
        return JSON.stringify({ success: false, message: `Player not found: ${args.player_name}` });
      }

      case 'run_strategy_backtest': {
        const result = await directQuery.runStrategyBacktest({
          strategy: args.strategy,
          league: args.league,
          season: args.season || new Date().getFullYear()
        });
        if (result) {
          return JSON.stringify({
            success: true,
            strategy: result.strategyName,
            league: result.league,
            season: result.season,
            totalBets: result.totalBets,
            record: `${result.wins}W - ${result.losses}L - ${result.pushes}P`,
            winRate: `${result.winRate.toFixed(1)}%`,
            roi: `${result.roi >= 0 ? '+' : ''}${result.roi.toFixed(1)}%`,
            netProfit: `$${result.netProfit.toFixed(2)}`,
            avgOdds: result.avgOdds > 0 ? `+${result.avgOdds.toFixed(0)}` : result.avgOdds.toFixed(0),
            sampleBets: result.sampleBets?.slice(0, 5)
          });
        }
        return JSON.stringify({ success: false, message: 'No backtest data available for this strategy' });
      }

      case 'get_team_roster': {
        const roster = await directQuery.getTeamRoster(args.team, args.league);
        if (roster) {
          return JSON.stringify({
            success: true,
            team: roster.team,
            teamFullName: roster.teamFullName,
            league: roster.league,
            playerCount: roster.players.length,
            players: roster.players.slice(0, 20)
          });
        }
        return JSON.stringify({ success: false, message: `Team not found: ${args.team}` });
      }

      case 'get_standings': {
        const standings = await directQuery.getStandings(args.league, args.season);
        if (standings.length > 0) {
          return JSON.stringify({
            success: true,
            league: args.league.toUpperCase(),
            season: args.season || new Date().getFullYear(),
            teams: standings.slice(0, 20).map((s: any) => ({
              team: s.team,
              wins: s.wins,
              losses: s.losses,
              conference: s.conference,
              division: s.division
            }))
          });
        }
        return JSON.stringify({ success: false, message: 'No standings data available' });
      }

      case 'get_player_props': {
        const props = await directQuery.getPlayerProps({
          player: args.player,
          team: args.team,
          league: args.league
        });
        if (props.length > 0) {
          return JSON.stringify({
            success: true,
            count: props.length,
            props: props.slice(0, 15).map((p: any) => ({
              player: p.playerName,
              game: `${p.awayTeam} @ ${p.homeTeam}`,
              market: p.market,
              line: p.line,
              overOdds: p.overOdds,
              underOdds: p.underOdds
            }))
          });
        }
        return JSON.stringify({ success: false, message: 'No player props found' });
      }

      case 'get_weather_impact': {
        const weather = await directQuery.getWeatherForGames({
          league: args.league,
          team: args.team
        });
        if (weather.length > 0) {
          return JSON.stringify({
            success: true,
            games: weather.slice(0, 10).map((w: any) => ({
              game: w.game,
              date: w.gameDate,
              temperature: w.temperature ? `${Math.round(w.temperature)}°F` : 'N/A',
              wind: w.windSpeed ? `${w.windSpeed} mph` : 'N/A',
              condition: w.condition,
              impact: w.impact,
              advice: w.bettingAdvice
            }))
          });
        }
        return JSON.stringify({ success: false, message: 'No weather data for outdoor games' });
      }

      case 'get_injuries': {
        const injuries = await directQuery.getInjuries({
          league: args.league,
          team: args.team
        });
        if (injuries.length > 0) {
          return JSON.stringify({
            success: true,
            count: injuries.length,
            injuries: injuries.slice(0, 15).map((i: any) => ({
              player: i.playerName,
              team: i.team,
              status: i.status,
              injury: i.injuryType,
              updated: i.updatedAt
            }))
          });
        }
        return JSON.stringify({ success: false, message: 'No injury data found' });
      }

      case 'get_betting_trends': {
        const trends = await directQuery.getBettingTrends({
          league: args.league,
          team: args.team
        });
        return JSON.stringify({
          success: true,
          atsRecords: trends.atsRecords?.slice(0, 10) || [],
          situational: trends.situational?.slice(0, 10) || []
        });
      }

      case 'search_sports': {
        const results = await directQuery.searchSports(args.query);
        return JSON.stringify({
          success: true,
          players: results.players.slice(0, 5).map(p => ({
            name: p.name,
            team: p.team,
            league: p.league,
            position: p.position
          })),
          teams: results.teams.slice(0, 5)
        });
      }

      case 'get_recent_games': {
        const games = await directQuery.getRecentGames({
          league: args.league,
          team: args.team,
          days: args.days || 7
        });
        return JSON.stringify({
          success: true,
          count: games.length,
          games: games.slice(0, 10).map(g => ({
            date: g.date,
            matchup: `${g.awayTeam} @ ${g.homeTeam}`,
            score: `${g.awayScore} - ${g.homeScore}`,
            winner: (g.homeScore || 0) > (g.awayScore || 0) ? g.homeTeam : g.awayTeam
          }))
        });
      }

      default:
        return JSON.stringify({ success: false, message: `Unknown tool: ${toolName}` });
    }
  } catch (error: any) {
    console.error(`[GrokTools] Error executing ${toolName}:`, error);
    return JSON.stringify({
      success: false,
      error: error.message || 'Tool execution failed'
    });
  }
}

/**
 * Format tool results for display
 */
export function formatToolResult(toolName: string, result: string): string {
  try {
    const data = JSON.parse(result);
    if (!data.success) {
      return `⚠️ ${data.message || data.error || 'No data found'}`;
    }

    switch (toolName) {
      case 'run_strategy_backtest':
        return `**Strategy Backtest: ${data.strategy}**
League: ${data.league.toUpperCase()} | Season: ${data.season}
- Record: ${data.record}
- Win Rate: ${data.winRate}
- ROI: ${data.roi}
- Net Profit: ${data.netProfit}`;

      case 'get_live_scores':
        return data.games.map((g: any) => `${g.matchup}: ${g.score} (${g.status})`).join('\n');

      default:
        return result;
    }
  } catch {
    return result;
  }
}
