import { getDb } from "../db.ts";
import { eq, gte, lte, and } from "drizzle-orm";
import { transactions, users, fraudAlerts, auditLogs } from "../../drizzle/schema.ts";

export interface ComplianceReport {
  reportId: string;
  reportType: "transaction_log" | "player_activity" | "rtp_verification" | "fraud_summary" | "financial_summary";
  generatedAt: number;
  period: {
    startDate: number;
    endDate: number;
  };
  data: Record<string, unknown>;
  summary: {
    totalRecords: number;
    totalAmount?: number;
    currency?: string;
    flaggedItems?: number;
  };
}

/**
 * Generate transaction log compliance report
 */
export async function generateTransactionLogReport(
  startDate: number,
  endDate: number
): Promise<ComplianceReport> {
  const db = await getDb();
  if (!db) {
    throw new Error("Database connection failed");
  }

  const txns = await db
    .select()
    .from(transactions)
    .where(and(gte(transactions.createdAt, new Date(startDate)), lte(transactions.createdAt, new Date(endDate))));

  const totalAmount = txns.reduce((sum, t) => sum + parseFloat(t.amount.toString()), 0);

  const report: ComplianceReport = {
    reportId: `txn_log_${Date.now()}`,
    reportType: "transaction_log",
    generatedAt: Date.now(),
    period: { startDate, endDate },
    data: {
      transactions: txns.map((t) => ({
        id: t.id,
        userId: t.userId,
        type: t.type,
        currency: t.currency,
        amount: t.amount,
        balanceBefore: t.balanceBefore,
        balanceAfter: t.balanceAfter,
        referenceId: t.referenceId,
        referenceType: t.referenceType,
        description: t.description,
        createdAt: t.createdAt,
      })),
    },
    summary: {
      totalRecords: txns.length,
      totalAmount,
      currency: "USD",
    },
  };

  return report;
}

/**
 * Generate player activity compliance report
 */
export async function generatePlayerActivityReport(
  startDate: number,
  endDate: number
): Promise<ComplianceReport> {
  const db = await getDb();
  if (!db) {
    throw new Error("Database connection failed");
  }

  const users_data = await db.select().from(users);

  const txns = await db
    .select()
    .from(transactions)
    .where(and(gte(transactions.createdAt, new Date(startDate)), lte(transactions.createdAt, new Date(endDate))));

  // Group transactions by user
  const playerActivity: Record<number, { bets: number; wins: number; totalWagered: number; totalWon: number }> = {};

  for (const txn of txns) {
    if (!playerActivity[txn.userId]) {
      playerActivity[txn.userId] = { bets: 0, wins: 0, totalWagered: 0, totalWon: 0 };
    }

    if (txn.type === "game_bet") {
      playerActivity[txn.userId].bets++;
      playerActivity[txn.userId].totalWagered += parseFloat(txn.amount.toString());
    } else if (txn.type === "game_win") {
      playerActivity[txn.userId].wins++;
      playerActivity[txn.userId].totalWon += parseFloat(txn.amount.toString());
    }
  }

  const report: ComplianceReport = {
    reportId: `player_activity_${Date.now()}`,
    reportType: "player_activity",
    generatedAt: Date.now(),
    period: { startDate, endDate },
    data: {
      playerActivity,
      activeUsers: Object.keys(playerActivity).length,
      totalPlayers: users_data.length,
    },
    summary: {
      totalRecords: Object.keys(playerActivity).length,
    },
  };

  return report;
}

/**
 * Generate RTP verification compliance report
 */
export async function generateRTPVerificationReport(
  startDate: number,
  endDate: number
): Promise<ComplianceReport> {
  const db = await getDb();
  if (!db) {
    throw new Error("Database connection failed");
  }

  const txns = await db
    .select()
    .from(transactions)
    .where(and(gte(transactions.createdAt, new Date(startDate)), lte(transactions.createdAt, new Date(endDate))));

  // Calculate RTP by game
  const gameStats: Record<string, { bets: number; wins: number; rtp: number }> = {};

  for (const txn of txns) {
    const gameId = txn.referenceId || "unknown";

    if (!gameStats[gameId]) {
      gameStats[gameId] = { bets: 0, wins: 0, rtp: 0 };
    }

    if (txn.type === "game_bet") {
      gameStats[gameId].bets += parseFloat(txn.amount.toString());
    } else if (txn.type === "game_win") {
      gameStats[gameId].wins += parseFloat(txn.amount.toString());
    }
  }

  // Calculate RTP percentages
  for (const gameId in gameStats) {
    const stats = gameStats[gameId];
    stats.rtp = stats.bets > 0 ? (stats.wins / stats.bets) * 100 : 0;
  }

  const report: ComplianceReport = {
    reportId: `rtp_verify_${Date.now()}`,
    reportType: "rtp_verification",
    generatedAt: Date.now(),
    period: { startDate, endDate },
    data: {
      gameStats,
      overallRTP: Object.values(gameStats).reduce((sum, g) => sum + g.rtp, 0) / Object.keys(gameStats).length,
    },
    summary: {
      totalRecords: Object.keys(gameStats).length,
    },
  };

  return report;
}

/**
 * Generate fraud summary compliance report
 */
export async function generateFraudSummaryReport(
  startDate: number,
  endDate: number
): Promise<ComplianceReport> {
  const db = await getDb();
  if (!db) {
    throw new Error("Database connection failed");
  }

  const frauds = await db
    .select()
    .from(fraudAlerts)
    .where(
      and(
        gte(fraudAlerts.createdAt, new Date(startDate)),
        lte(fraudAlerts.createdAt, new Date(endDate))
      )
    );

  const fraudByType: Record<string, number> = {};
  const fraudBySeverity: Record<string, number> = {};

  for (const fraud of frauds) {
    const alertType = fraud.alertType || 'unknown';
    fraudByType[alertType] = (fraudByType[alertType] || 0) + 1;
    fraudBySeverity[fraud.severity] = (fraudBySeverity[fraud.severity] || 0) + 1;
  }

  const report: ComplianceReport = {
    reportId: `fraud_summary_${Date.now()}`,
    reportType: "fraud_summary",
    generatedAt: Date.now(),
    period: { startDate, endDate },
    data: {
      fraudByType,
      fraudBySeverity,
      totalFraudAlerts: frauds.length,
      criticalAlerts: fraudBySeverity["critical"] || 0,
      highAlerts: fraudBySeverity["high"] || 0,
    },
    summary: {
      totalRecords: frauds.length,
      flaggedItems: frauds.length,
    },
  };

  return report;
}

/**
 * Generate financial summary compliance report
 */
export async function generateFinancialSummaryReport(
  startDate: number,
  endDate: number
): Promise<ComplianceReport> {
  const db = await getDb();
  if (!db) {
    throw new Error("Database connection failed");
  }

  const txns = await db
    .select()
    .from(transactions)
    .where(and(gte(transactions.createdAt, new Date(startDate)), lte(transactions.createdAt, new Date(endDate))));

  const byCurrency: Record<string, { totalBets: number; totalWins: number; revenue: number }> = {};

  for (const txn of txns) {
    const currency = txn.currency;

    if (!byCurrency[currency]) {
      byCurrency[currency] = { totalBets: 0, totalWins: 0, revenue: 0 };
    }

    const amount = parseFloat(txn.amount.toString());

    if (txn.type === "game_bet") {
      byCurrency[currency].totalBets += amount;
    } else if (txn.type === "game_win") {
      byCurrency[currency].totalWins += amount;
    }
  }

  // Calculate revenue (bets - wins)
  for (const currency in byCurrency) {
    byCurrency[currency].revenue = byCurrency[currency].totalBets - byCurrency[currency].totalWins;
  }

  const report: ComplianceReport = {
    reportId: `financial_summary_${Date.now()}`,
    reportType: "financial_summary",
    generatedAt: Date.now(),
    period: { startDate, endDate },
    data: {
      byCurrency,
      totalTransactions: txns.length,
    },
    summary: {
      totalRecords: txns.length,
      totalAmount: Object.values(byCurrency).reduce((sum, c) => sum + c.totalBets, 0),
      currency: "Multi-currency",
    },
  };

  return report;
}

/**
 * Export report to CSV format
 */
export function exportReportToCSV(report: ComplianceReport): string {
  let csv = `Compliance Report: ${report.reportType}\n`;
  csv += `Generated: ${new Date(report.generatedAt).toISOString()}\n`;
  csv += `Period: ${new Date(report.period.startDate).toISOString()} to ${new Date(report.period.endDate).toISOString()}\n\n`;

  if (report.reportType === "transaction_log" && Array.isArray(report.data.transactions)) {
    csv += "ID,User ID,Type,Currency,Amount,Balance Before,Balance After,Reference ID,Reference Type,Description,Created At\n";
    for (const txn of report.data.transactions) {
      csv += `${txn.id},${txn.userId},${txn.type},${txn.currency},${txn.amount},${txn.balanceBefore},${txn.balanceAfter},${txn.referenceId},${txn.referenceType},"${txn.description}",${txn.createdAt}\n`;
    }
  } else {
    csv += JSON.stringify(report.data, null, 2);
  }

  return csv;
}

/**
 * Export report to JSON format
 */
export function exportReportToJSON(report: ComplianceReport): string {
  return JSON.stringify(report, null, 2);
}
