/**
 * Repair Feeder - Fix incomplete matches
 * Usage: npm run feeder:repair
 *
 * Finds matches in DB that are missing stats or lineups
 * and re-fetches them from the API.
 */

import { NestFactory } from "@nestjs/core";
import { Logger } from "@nestjs/common";
import { PrismaService } from "../database/prisma.service";
import { FeederService } from "../modules/feeder/feeder.service";

async function bootstrap() {
  process.env.FEEDER_MODE = "historical";

  const logger = new Logger("FeederRepair");

  logger.log("🔧 Starting feeder repair scan...");

  // eslint-disable-next-line @typescript-eslint/no-require-imports
  const { AppModule } = require("../app.module");
  const app = await NestFactory.createApplicationContext(AppModule, {
    logger: ["log", "error", "warn"],
  });

  const prisma = app.get(PrismaService);
  const feederService = app.get(FeederService);

  try {
    // Find football matches missing stats (no football_team_stats rows)
    const matchesMissingStats = await prisma.$queryRaw<
      Array<{ id: string; match_name: string }>
    >`
      SELECT m.id, m.match_name
      FROM matches m
      LEFT JOIN football_team_stats fts ON fts.match_id = m.id
      WHERE m.sport = 'football'
        AND m.state = 'Ended'
        AND fts.id IS NULL
      ORDER BY m.mst_utc DESC
    `;

    // Find football matches missing lineups (< 18 participation rows)
    const matchesMissingLineups = await prisma.$queryRaw<
      Array<{ id: string; match_name: string; cnt: bigint }>
    >`
      SELECT m.id, m.match_name, COUNT(mpp.id) as cnt
      FROM matches m
      LEFT JOIN match_player_participation mpp ON mpp.match_id = m.id
      WHERE m.sport = 'football'
        AND m.state = 'Ended'
      GROUP BY m.id, m.match_name
      HAVING COUNT(mpp.id) < 18
      ORDER BY m.mst_utc DESC
    `;

    // Combine unique match IDs
    const repairSet = new Set<string>();
    for (const m of matchesMissingStats) repairSet.add(m.id);
    for (const m of matchesMissingLineups) repairSet.add(m.id);

    logger.log(
      `📊 Found ${repairSet.size} incomplete matches (${matchesMissingStats.length} missing stats, ${matchesMissingLineups.length} missing lineups)`,
    );

    if (repairSet.size === 0) {
      logger.log("✅ No incomplete matches found. Everything is clean!");
      await app.close();
      process.exit(0);
    }

    let repaired = 0;
    let failed = 0;
    const matchIds = Array.from(repairSet);

    for (let i = 0; i < matchIds.length; i++) {
      const matchId = matchIds[i];

      // Rate limiting
      if (i > 0 && i % 10 === 0) {
        logger.log(
          `⏸️ Cooldown after 10 repairs... (${repaired} repaired, ${failed} failed, ${matchIds.length - i} remaining)`,
        );
        await new Promise((r) => setTimeout(r, 5000));
      }

      await new Promise((r) => setTimeout(r, 500));

      try {
        const result = await feederService.refreshMatch(matchId, "all");
        if (result.success) {
          repaired++;
          if (repaired % 25 === 0) {
            logger.log(`🔧 Progress: ${repaired}/${matchIds.length} repaired`);
          }
        } else {
          failed++;
          logger.warn(
            `❌ [${matchId}] Repair failed: ${result.error || "unknown"}`,
          );
        }
      } catch (e: any) {
        failed++;
        logger.error(`❌ [${matchId}] Repair exception: ${e.message}`);
      }
    }

    logger.log(
      `🎉 REPAIR COMPLETE: ${repaired} repaired, ${failed} failed out of ${matchIds.length} total`,
    );
  } catch (error: any) {
    logger.error(`❌ Repair failed: ${error.message}`);
    logger.error(error.stack);
    process.exit(1);
  } finally {
    await app.close();
  }

  process.exit(0);
}

void bootstrap();
