/**
 * Baseline Capture Script - Phase 1a Task 0
 *
 * Captures the current state of qualifying-points data to JSON fixtures for
 * verification across all 5 migration phases. This ensures no scoring drift
 * occurs during the canonical tournament layer migration.
 *
 * Captured data:
 * 1. participant_qualifying_totals rows for all qualifying_points sports_seasons
 * 2. event_results rows with non-null qualifying_points_awarded
 * 3. participant_surface_elos rows for tennis sports_seasons
 * 4. Monte Carlo simulator output for each in-flight qualifying-points season
 *
 * WARNING: Simulator output is NON-DETERMINISTIC. The current simulator
 * implementations use Math.random() directly without seed support. This means
 * simulator fixture files will differ on each run and cannot be used for exact
 * byte-for-byte comparisons. They serve as reference baselines for manual
 * review and approximate validation only.
 */

import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { eq, sql } from "drizzle-orm";
import { writeFileSync, mkdirSync } from "fs";
import { join } from "path";
import * as schema from "../database/schema.js";
import { getSimulator } from "../app/services/simulations/registry.js";

const OUT_DIR = join(process.cwd(), "test-fixtures", "baselines");

async function main() {
  const dbUrl = process.env.DATABASE_URL;
  if (!dbUrl) {
    console.error("ERROR: DATABASE_URL is required");
    process.exit(1);
  }

  console.log("Connecting to database...");
  const client = postgres(dbUrl, { max: 1 });
  const db = drizzle(client, { schema });

  mkdirSync(OUT_DIR, { recursive: true });
  console.log(`Output directory: ${OUT_DIR}\n`);

  // ─── 1. Capture participant_qualifying_totals ─────────────────────────────────

  console.log("Capturing participant_qualifying_totals...");
  const qpTotals = await db.execute(sql`
    SELECT pqt.*, ss.id as sports_season_id, ss.name as sports_season_name, s.name as sport_name
    FROM participant_qualifying_totals pqt
    JOIN sports_seasons ss ON ss.id = pqt.sports_season_id
    JOIN sports s ON s.id = ss.sport_id
    WHERE ss.scoring_pattern = 'qualifying_points'
    ORDER BY ss.id, pqt.participant_id
  `);

  writeFileSync(
    join(OUT_DIR, "qp-totals-pre-phase1.json"),
    JSON.stringify(qpTotals, null, 2)
  );
  console.log(`  Wrote ${qpTotals.length} rows → qp-totals-pre-phase1.json`);

  // ─── 2. Capture event_results with qualifying_points_awarded ─────────────────

  console.log("Capturing event_results with qualifying_points_awarded...");
  const eventResults = await db.execute(sql`
    SELECT er.*, se.sports_season_id, se.name as event_name
    FROM event_results er
    JOIN scoring_events se ON se.id = er.scoring_event_id
    JOIN sports_seasons ss ON ss.id = se.sports_season_id
    WHERE ss.scoring_pattern = 'qualifying_points'
      AND er.qualifying_points_awarded IS NOT NULL
    ORDER BY se.sports_season_id, er.scoring_event_id, er.participant_id
  `);

  writeFileSync(
    join(OUT_DIR, "event-results-pre-phase1.json"),
    JSON.stringify(eventResults, null, 2)
  );
  console.log(`  Wrote ${eventResults.length} rows → event-results-pre-phase1.json`);

  // ─── 3. Capture participant_surface_elos ──────────────────────────────────────

  console.log("Capturing participant_surface_elos...");
  const surfaceElos = await db.execute(sql`
    SELECT pse.*, ss.sport_id, ss.name as sports_season_name, s.name as sport_name
    FROM participant_surface_elos pse
    JOIN sports_seasons ss ON ss.id = pse.sports_season_id
    JOIN sports s ON s.id = ss.sport_id
    WHERE ss.scoring_pattern = 'qualifying_points'
    ORDER BY ss.id, pse.participant_id
  `);

  writeFileSync(
    join(OUT_DIR, "surface-elos-pre-phase1.json"),
    JSON.stringify(surfaceElos, null, 2)
  );
  console.log(`  Wrote ${surfaceElos.length} rows → surface-elos-pre-phase1.json`);

  // ─── 4. Capture simulator output for in-flight qualifying-points seasons ─────

  console.log("\nCapturing Monte Carlo simulator output...");
  const inFlightSeasons = await db
    .select()
    .from(schema.sportsSeasons)
    .where(eq(schema.sportsSeasons.scoringPattern, "qualifying_points"));

  console.log(`  Found ${inFlightSeasons.length} qualifying-points sports_seasons`);

  let simCount = 0;
  for (const ss of inFlightSeasons) {
    if (!ss.simulatorType) {
      console.log(`  Skipping ${ss.name} (id: ${ss.id}) - no simulatorType set`);
      continue;
    }

    console.log(`  Running simulator for ${ss.name} (type: ${ss.simulatorType})...`);
    try {
      const sim = getSimulator(ss.simulatorType);

      // NOTE: Simulators do not accept seed parameter - output is non-deterministic
      const output = await sim.simulate(ss.id);

      const filename = `sim-output-${ss.simulatorType}-${ss.id}.json`;
      writeFileSync(
        join(OUT_DIR, filename),
        JSON.stringify(output, null, 2)
      );
      console.log(`    Wrote ${output.length} results → ${filename}`);
      simCount++;
    } catch (err) {
      console.error(`    ERROR simulating ${ss.name}:`, err);
      // Continue with other seasons even if one fails
    }
  }

  console.log(`\n✓ Baseline capture complete!`);
  console.log(`  ${qpTotals.length} QP totals`);
  console.log(`  ${eventResults.length} event results`);
  console.log(`  ${surfaceElos.length} surface elo rows`);
  console.log(`  ${simCount} simulator outputs (non-deterministic)`);
  console.log(`\nOutput: ${OUT_DIR}`);

  await client.end();
}

main()
  .then(() => process.exit(0))
  .catch((e) => {
    console.error("FATAL:", e);
    process.exit(1);
  });
