#!/usr/bin/env npx tsx
/**
 * Add Missing SGO Players Script
 *
 * Creates canonical players from SGO prop IDs that weren't in the BallDontLie data.
 */

import { PrismaClient } from '../prisma_sports/generated/sports-client';

const prisma = new PrismaClient();

function normalizePlayerName(name: string): string {
  if (!name) return '';
  return name
    .toLowerCase()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .replace(/\s+(jr\.?|sr\.?|iii|ii|iv|v)$/i, '')
    .replace(/\./g, '')
    .replace(/\s+/g, ' ')
    .trim();
}

function parseSgoPlayerId(sgoId: string): { firstName: string; lastName: string; name: string; league: string } | null {
  if (!sgoId || typeof sgoId !== 'string') return null;
  const leagueMatch = sgoId.match(/_(NBA|NFL|NHL|MLB|WNBA|NCAAB|NCAAF|MMA|UFC)$/i);
  if (!leagueMatch) return null;
  const league = leagueMatch[1].toLowerCase();
  const withoutLeague = sgoId.slice(0, -leagueMatch[0].length);
  const parts = withoutLeague.split('_');
  const lastPart = parts[parts.length - 1];
  if (!/^\d+$/.test(lastPart)) return null;
  const nameParts = parts.slice(0, -1);
  const firstName = nameParts[0] || '';
  const lastName = nameParts.slice(1).join(' ') || '';
  const name = nameParts.join(' ').toLowerCase();
  return { firstName, lastName, name, league };
}

function formatName(parsed: { firstName: string; lastName: string }): string {
  const first = parsed.firstName.charAt(0).toUpperCase() + parsed.firstName.slice(1).toLowerCase();
  const last = parsed.lastName
    .split(' ')
    .map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
    .join(' ');
  return last ? `${first} ${last}` : first;
}

async function createMissingSGOPlayers() {
  console.log('Finding SGO player IDs without canonical players...\n');

  for (const league of ['nba', 'nfl', 'nhl', 'mlb']) {
    // Find distinct playerExternalIds that look like SGO IDs and have no canonical link
    const props = await prisma.playerPropLine.findMany({
      where: {
        league,
        canonicalPlayerId: null,
        playerExternalId: { contains: '_' }
      },
      select: { playerExternalId: true },
      distinct: ['playerExternalId'],
    });

    const sgoIds = props
      .map(p => p.playerExternalId)
      .filter(id => id.endsWith(`_${league.toUpperCase()}`));

    console.log(`${league.toUpperCase()}: ${sgoIds.length} SGO player IDs without canonical`);

    let created = 0;
    let existed = 0;
    let linked = 0;

    for (const sgoId of sgoIds) {
      const parsed = parseSgoPlayerId(sgoId);
      if (!parsed) continue;

      const normalizedName = normalizePlayerName(parsed.name);

      // Check if canonical player exists by name
      const existing = await prisma.canonicalPlayer.findUnique({
        where: { league_normalizedName: { league, normalizedName } }
      });

      if (existing) {
        existed++;
        // Create alias if not exists
        const aliasExists = await prisma.playerAlias.findFirst({
          where: { alias: sgoId }
        });
        if (!aliasExists) {
          try {
            await prisma.playerAlias.create({
              data: {
                playerId: existing.id,
                source: 'sgo',
                alias: sgoId,
                aliasType: 'external_id'
              }
            });
          } catch (e) {
            // Alias may already exist, ignore
          }
        }
        // Update props
        const updated = await prisma.playerPropLine.updateMany({
          where: { league, playerExternalId: sgoId, canonicalPlayerId: null },
          data: { canonicalPlayerId: existing.id }
        });
        linked += updated.count;
        continue;
      }

      // Create new canonical player
      const fullName = formatName(parsed);

      try {
        const newPlayer = await prisma.canonicalPlayer.create({
          data: {
            league,
            fullName,
            normalizedName,
            sgoId
          }
        });

        // Create alias
        await prisma.playerAlias.create({
          data: {
            playerId: newPlayer.id,
            source: 'sgo',
            alias: sgoId,
            aliasType: 'external_id'
          }
        });

        // Link props
        const updated = await prisma.playerPropLine.updateMany({
          where: { league, playerExternalId: sgoId, canonicalPlayerId: null },
          data: { canonicalPlayerId: newPlayer.id }
        });

        created++;
        linked += updated.count;
      } catch (e) {
        // Player might already exist with different normalization
      }
    }

    console.log(`  Created: ${created}, Found existing: ${existed}, Props linked: ${linked}`);
  }

  await prisma.$disconnect();
  console.log('\nDone!');
}

createMissingSGOPlayers().catch((e) => {
  console.error('Failed:', e);
  process.exit(1);
});
