/**
 * Data Freshness Monitoring API
 *
 * Provides visibility into data quality, coverage rates, and sync status
 * to prevent stale data issues (e.g., traded players showing wrong teams).
 *
 * GET /api/admin/data-freshness
 */

import { NextResponse } from 'next/server';
import { getSportsDb, isSportsDbEnabled } from '@/lib/sportsDb';

export const dynamic = 'force-dynamic';

interface CoverageStats {
  league: string;
  total: number;
  linked: number;
  percentage: number;
}

interface DataFreshnessReport {
  timestamp: string;
  status: 'healthy' | 'warning' | 'critical';
  issues: string[];

  // Canonical coverage
  propLineCoverage: CoverageStats[];
  metricCoverage: CoverageStats[];

  // Entity counts
  entityCounts: {
    canonicalPlayers: number;
    canonicalTeams: number;
    canonicalGames: number;
    playerAliases: number;
  };

  // Recent data freshness
  recentActivity: {
    propsLast24h: number;
    metricsLast24h: number;
    gamesLast24h: number;
  };

  // Roster freshness (critical for trades)
  rosterFreshness: {
    playersWithTeam: number;
    playersWithoutTeam: number;
    recentlyUpdated: number;
  };

  // Last sync timestamps
  lastSyncs: {
    canonicalRosters: string | null;
    propLines: string | null;
    metrics: string | null;
  };
}

export async function GET(request: Request) {
  if (!isSportsDbEnabled()) {
    return NextResponse.json({ error: 'SportsDB not enabled' }, { status: 503 });
  }

  const sports = getSportsDb();
  const issues: string[] = [];
  const now = new Date();
  const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);

  try {
    // 1. Get prop line coverage by league
    const propLineCoverage: CoverageStats[] = [];
    for (const league of ['nba', 'nfl', 'nhl', 'mlb']) {
      const total = await sports.playerPropLine.count({ where: { league } });
      const linked = await sports.playerPropLine.count({
        where: { league, NOT: { canonicalPlayerId: null } }
      });
      const percentage = total > 0 ? Math.round((linked / total) * 1000) / 10 : 0;
      propLineCoverage.push({ league, total, linked, percentage });

      // Flag low coverage
      if (total > 1000 && percentage < 80) {
        issues.push(`${league.toUpperCase()} prop line coverage is low: ${percentage}%`);
      }
    }

    // 2. Get metric coverage by league
    const metricCoverage: CoverageStats[] = [];
    for (const league of ['nba', 'nfl', 'nhl', 'mlb']) {
      const total = await sports.playerGameMetric.count({ where: { league } });
      const linked = await sports.playerGameMetric.count({
        where: { league, NOT: { canonicalPlayerId: null } }
      });
      const percentage = total > 0 ? Math.round((linked / total) * 1000) / 10 : 0;
      metricCoverage.push({ league, total, linked, percentage });

      // Flag low coverage
      if (total > 10000 && percentage < 70) {
        issues.push(`${league.toUpperCase()} metric coverage is low: ${percentage}%`);
      }
    }

    // 3. Entity counts
    const [players, teams, games, aliases] = await Promise.all([
      sports.canonicalPlayer.count(),
      sports.canonicalTeam.count(),
      sports.canonicalGame.count(),
      sports.playerAlias.count(),
    ]);

    if (players < 5000) {
      issues.push(`Low canonical player count: ${players} (expected 10,000+)`);
    }

    // 4. Recent activity (data freshness indicator)
    const [propsLast24h, metricsLast24h, gamesLast24h] = await Promise.all([
      sports.playerPropLine.count({
        where: { createdAt: { gte: yesterday } }
      }),
      sports.playerGameMetric.count({
        where: { createdAt: { gte: yesterday } }
      }),
      sports.canonicalGame.count({
        where: { createdAt: { gte: yesterday } }
      }),
    ]);

    if (propsLast24h === 0) {
      issues.push('No new prop lines in the last 24 hours');
    }

    // 5. Roster freshness (critical for trade accuracy)
    const [playersWithTeam, playersWithoutTeam, recentlyUpdated] = await Promise.all([
      sports.canonicalPlayer.count({
        where: { NOT: { teamId: null } }
      }),
      sports.canonicalPlayer.count({
        where: { teamId: null }
      }),
      sports.canonicalPlayer.count({
        where: { updatedAt: { gte: yesterday } }
      }),
    ]);

    const teamCoverage = (playersWithTeam / (playersWithTeam + playersWithoutTeam)) * 100;
    if (teamCoverage < 70) {
      issues.push(`Only ${teamCoverage.toFixed(1)}% of players have team assignments`);
    }

    // 6. Check last sync timestamps from logs
    let lastCanonicalSync: string | null = null;
    try {
      const fs = await import('fs/promises');
      const syncFile = '/var/www/html/eventheodds/logs/last-canonical-sync.txt';
      const content = await fs.readFile(syncFile, 'utf-8').catch(() => null);
      lastCanonicalSync = content?.trim() || null;

      // Check if sync is stale (more than 48 hours old)
      if (lastCanonicalSync) {
        const syncDate = new Date(lastCanonicalSync);
        const hoursSinceSync = (now.getTime() - syncDate.getTime()) / (1000 * 60 * 60);
        if (hoursSinceSync > 48) {
          issues.push(`Canonical roster sync is ${Math.round(hoursSinceSync)} hours old`);
        }
      }
    } catch (e) {
      // File doesn't exist yet
    }

    // Get most recent prop and metric timestamps
    const [latestProp, latestMetric] = await Promise.all([
      sports.playerPropLine.findFirst({
        orderBy: { createdAt: 'desc' },
        select: { createdAt: true }
      }),
      sports.playerGameMetric.findFirst({
        orderBy: { createdAt: 'desc' },
        select: { createdAt: true }
      }),
    ]);

    // Determine overall status
    let status: 'healthy' | 'warning' | 'critical' = 'healthy';
    if (issues.length >= 3) {
      status = 'critical';
    } else if (issues.length >= 1) {
      status = 'warning';
    }

    const report: DataFreshnessReport = {
      timestamp: now.toISOString(),
      status,
      issues,
      propLineCoverage,
      metricCoverage,
      entityCounts: {
        canonicalPlayers: players,
        canonicalTeams: teams,
        canonicalGames: games,
        playerAliases: aliases,
      },
      recentActivity: {
        propsLast24h,
        metricsLast24h,
        gamesLast24h,
      },
      rosterFreshness: {
        playersWithTeam,
        playersWithoutTeam,
        recentlyUpdated,
      },
      lastSyncs: {
        canonicalRosters: lastCanonicalSync,
        propLines: latestProp?.createdAt?.toISOString() || null,
        metrics: latestMetric?.createdAt?.toISOString() || null,
      },
    };

    return NextResponse.json(report);
  } catch (error) {
    console.error('[DataFreshness] Error:', error);
    return NextResponse.json(
      { error: 'Failed to generate data freshness report', details: String(error) },
      { status: 500 }
    );
  }
}
