import dotenv from 'dotenv';
import path from 'path';
import { randomUUID } from 'crypto';

dotenv.config({ path: path.join(__dirname, '../../.env') });

import pool from '../db';
import { buildDedupIdentity, chooseSiblingWinner, type DedupCandidate } from '../services/prop-dedup';

const SUPPRESS_REASON = 'SUPPRESSED_SIBLING';

interface PrecomputedPropRow extends DedupCandidate {
  id: string;
  event_id: string;
  league: string;
  team_id: string | null;
  team_side: string | null;
  player_name: string | null;
  forecast_type: string;
  forecast_payload: Record<string, any> | null;
}

function suppressionEnabled(): boolean {
  return process.env.PI_SIBLING_SUPPRESSION_ENABLED === 'true';
}

function buildSyntheticPlayerId(row: PrecomputedPropRow): string {
  return `${row.event_id}:${buildDedupIdentity(row)}:${row.id}`;
}

function buildConflictPayload(winner: PrecomputedPropRow, loser: PrecomputedPropRow) {
  return {
    source: 'pi-sibling-scanner',
    identityKey: buildDedupIdentity(loser),
    suppressedAssetId: loser.id,
    winnerAssetId: winner.id,
    winnerPlayer: winner.player_name,
    winnerProp: winner.forecast_payload?.prop ?? null,
    loserProp: loser.forecast_payload?.prop ?? null,
  };
}

export async function runSiblingSuppressionWorker(db: { query: Function; end?: Function } = pool) {
  if (!suppressionEnabled()) {
    return { skipped: true, suppressed: 0 };
  }

  const runId = randomUUID();
  const { rows } = await db.query(
    `SELECT id, event_id, league, team_id, team_side, player_name, forecast_type, forecast_payload
     FROM rm_forecast_precomputed
     WHERE forecast_type = 'PLAYER_PROP' AND status = 'ACTIVE'
     ORDER BY event_id, confidence_score DESC NULLS LAST, generated_at DESC`
  );

  const groups = new Map<string, PrecomputedPropRow[]>();
  for (const row of rows as PrecomputedPropRow[]) {
    const key = `${row.event_id}:${buildDedupIdentity(row)}`;
    const existing = groups.get(key) ?? [];
    existing.push(row);
    groups.set(key, existing);
  }

  const suppressed: Array<{ winner: PrecomputedPropRow; loser: PrecomputedPropRow }> = [];
  groups.forEach((group) => {
    if (group.length < 2) return;
    const { winner, losers } = chooseSiblingWinner(group);
    losers.forEach((loser) => suppressed.push({ winner, loser }));
  });

  await db.query(`DELETE FROM pi_prop_eligibility WHERE suppress_reason = $1`, [SUPPRESS_REASON]);

  for (const item of suppressed) {
    await db.query(
      `INSERT INTO pi_prop_eligibility
         (id, run_id, game_id, player_id, player_name, team_id, league,
          validation_state, market_presence_flag,
          roster_verified_at, availability_verified_at, lineup_verified_at,
          suppress_reason, suppress_reason_human, winning_source,
          conflict_payload, publish_allowed)
       VALUES
         ($1, $2, $3, $4, $5, $6, $7,
          $8, $9,
          $10, $11, $12,
          $13, $14, $15,
          $16, $17)
       ON CONFLICT (game_id, player_id) DO UPDATE SET
         run_id = EXCLUDED.run_id,
         validation_state = EXCLUDED.validation_state,
         market_presence_flag = EXCLUDED.market_presence_flag,
         roster_verified_at = EXCLUDED.roster_verified_at,
         availability_verified_at = EXCLUDED.availability_verified_at,
         lineup_verified_at = EXCLUDED.lineup_verified_at,
         suppress_reason = EXCLUDED.suppress_reason,
         suppress_reason_human = EXCLUDED.suppress_reason_human,
         winning_source = EXCLUDED.winning_source,
         conflict_payload = EXCLUDED.conflict_payload,
         publish_allowed = EXCLUDED.publish_allowed,
         updated_at = NOW()`,
      [
        randomUUID(),
        runId,
        item.loser.event_id,
        buildSyntheticPlayerId(item.loser),
        item.loser.player_name,
        item.loser.team_id,
        item.loser.league,
        SUPPRESS_REASON,
        true,
        null,
        null,
        null,
        SUPPRESS_REASON,
        `Suppressed sibling prop in favor of higher-ranked offer for ${item.loser.player_name}`,
        item.winner.id,
        JSON.stringify(buildConflictPayload(item.winner, item.loser)),
        false,
      ]
    );
  }

  return { skipped: false, suppressed: suppressed.length };
}

export async function main() {
  try {
    const result = await runSiblingSuppressionWorker();
    if (result.skipped) {
      console.log('[pi-sibling-scanner] PI_SIBLING_SUPPRESSION_ENABLED=false, skipping');
    } else {
      console.log(`[pi-sibling-scanner] Suppressed ${result.suppressed} sibling props`);
    }
  } catch (error) {
    console.error('[pi-sibling-scanner] Worker failed:', error);
    process.exitCode = 1;
  } finally {
    await pool.end();
  }
}

if (require.main === module) {
  main();
}
