/**
 * Scheduled Report Generation System
 * Automatically generate and email reports to admins
 */

export interface ScheduledReport {
  id: string;
  name: string;
  type: 'payment' | 'reconciliation' | 'fraud' | 'withdrawal' | 'analytics';
  schedule: 'daily' | 'weekly' | 'monthly';
  time: string; // HH:mm format
  recipients: string[]; // email addresses
  format: 'csv' | 'json' | 'pdf' | 'html';
  enabled: boolean;
  lastRun?: Date;
  nextRun?: Date;
  createdAt: Date;
  updatedAt: Date;
}

export interface ReportExecution {
  id: string;
  reportId: string;
  startTime: Date;
  endTime?: Date;
  status: 'pending' | 'processing' | 'completed' | 'failed';
  recordsProcessed: number;
  fileSize: number;
  downloadUrl?: string;
  error?: string;
}

export interface ReportContent {
  title: string;
  generatedAt: Date;
  timeRange: string;
  summary: Record<string, any>;
  details: Record<string, any>;
  charts: Array<{
    title: string;
    type: 'line' | 'bar' | 'pie' | 'table';
    data: any;
  }>;
}

/**
 * Create scheduled report
 */
export function createScheduledReport(
  name: string,
  type: ScheduledReport['type'],
  schedule: ScheduledReport['schedule'],
  time: string,
  recipients: string[],
  format: ScheduledReport['format'] = 'pdf'
): ScheduledReport {
  return {
    id: `SREPORT-${Date.now()}`,
    name,
    type,
    schedule,
    time,
    recipients,
    format,
    enabled: true,
    createdAt: new Date(),
    updatedAt: new Date(),
  };
}

/**
 * Get next report run time
 */
export function getNextReportRunTime(report: ScheduledReport): Date {
  const now = new Date();
  const [hours, minutes] = report.time.split(':').map(Number);

  let next = new Date(now);
  next.setHours(hours, minutes, 0, 0);

  if (next <= now) {
    if (report.schedule === 'daily') {
      next.setDate(next.getDate() + 1);
    } else if (report.schedule === 'weekly') {
      next.setDate(next.getDate() + 7);
    } else if (report.schedule === 'monthly') {
      next.setMonth(next.getMonth() + 1);
    }
  }

  return next;
}

/**
 * Generate payment report
 */
export function generatePaymentReport(
  timeRange: '7d' | '30d' | '90d',
  metrics: any
): ReportContent {
  const daysAgo = timeRange === '7d' ? 7 : timeRange === '30d' ? 30 : 90;
  const startDate = new Date();
  startDate.setDate(startDate.getDate() - daysAgo);

  return {
    title: 'Payment Report',
    generatedAt: new Date(),
    timeRange: `Last ${daysAgo} days`,
    summary: {
      totalRevenue: metrics.totalRevenue,
      totalTransactions: metrics.totalTransactions,
      averageTransaction: metrics.averageTransaction,
      successRate: metrics.successRate,
    },
    details: {
      dailyBreakdown: [
        { date: '2026-04-21', revenue: 25500, transactions: 510 },
        { date: '2026-04-20', revenue: 20700, transactions: 414 },
        { date: '2026-04-19', revenue: 22500, transactions: 450 },
      ],
      paymentMethods: [
        { method: 'Square', count: 1200, amount: 60000 },
        { method: 'PayPal', count: 650, amount: 32500 },
      ],
    },
    charts: [
      {
        title: 'Daily Revenue Trend',
        type: 'line',
        data: { labels: ['Day 1', 'Day 2', 'Day 3'], datasets: [{ data: [18000, 19500, 17800] }] },
      },
      {
        title: 'Payment Method Distribution',
        type: 'pie',
        data: { labels: ['Square', 'PayPal', 'Google Pay'], datasets: [{ data: [48, 26, 16] }] },
      },
    ],
  };
}

/**
 * Generate reconciliation report
 */
export function generateReconciliationReport(
  reconciliations: any[]
): ReportContent {
  const totalRecords = reconciliations.reduce((sum, r) => sum + r.totalRecords, 0);
  const totalMatched = reconciliations.reduce((sum, r) => sum + r.totalMatched, 0);
  const totalDiscrepancies = reconciliations.reduce((sum, r) => sum + r.totalDiscrepancies, 0);

  return {
    title: 'Reconciliation Report',
    generatedAt: new Date(),
    timeRange: 'Last 7 days',
    summary: {
      totalRecords,
      totalMatched,
      totalDiscrepancies,
      matchRate: ((totalMatched / totalRecords) * 100).toFixed(1),
    },
    details: {
      byProvider: reconciliations.map(r => ({
        provider: r.provider,
        records: r.totalRecords,
        matched: r.totalMatched,
        discrepancies: r.totalDiscrepancies,
      })),
    },
    charts: [
      {
        title: 'Match Rate by Provider',
        type: 'bar',
        data: {
          labels: reconciliations.map(r => r.provider),
          datasets: [{ data: reconciliations.map(r => ((r.totalMatched / r.totalRecords) * 100).toFixed(1)) }],
        },
      },
    ],
  };
}

/**
 * Generate fraud report
 */
export function generateFraudReport(
  fraudScores: any[]
): ReportContent {
  const critical = fraudScores.filter(f => f.risk === 'critical').length;
  const high = fraudScores.filter(f => f.risk === 'high').length;
  const medium = fraudScores.filter(f => f.risk === 'medium').length;

  return {
    title: 'Fraud Detection Report',
    generatedAt: new Date(),
    timeRange: 'Last 7 days',
    summary: {
      totalAnalyzed: fraudScores.length,
      criticalCount: critical,
      highCount: high,
      mediumCount: medium,
      blockRate: ((fraudScores.filter(f => f.action === 'blocked').length / fraudScores.length) * 100).toFixed(1),
    },
    details: {
      topIndicators: [
        { indicator: 'Velocity Checks', count: 45 },
        { indicator: 'Amount Anomalies', count: 32 },
        { indicator: 'Geographic Anomalies', count: 28 },
      ],
    },
    charts: [
      {
        title: 'Risk Distribution',
        type: 'pie',
        data: {
          labels: ['Critical', 'High', 'Medium', 'Low'],
          datasets: [{ data: [critical, high, medium, fraudScores.filter(f => f.risk === 'low').length] }],
        },
      },
    ],
  };
}

/**
 * Generate withdrawal report
 */
export function generateWithdrawalReport(
  withdrawals: any[]
): ReportContent {
  const approved = withdrawals.filter(w => w.status === 'approved').length;
  const pending = withdrawals.filter(w => w.status === 'pending').length;
  const rejected = withdrawals.filter(w => w.status === 'rejected').length;
  const totalAmount = withdrawals.reduce((sum, w) => sum + w.amount, 0);

  return {
    title: 'Withdrawal Report',
    generatedAt: new Date(),
    timeRange: 'Last 7 days',
    summary: {
      totalWithdrawals: withdrawals.length,
      totalAmount,
      approved,
      pending,
      rejected,
      averageAmount: (totalAmount / withdrawals.length).toFixed(2),
    },
    details: {
      byStatus: [
        { status: 'Approved', count: approved, amount: withdrawals.filter(w => w.status === 'approved').reduce((sum, w) => sum + w.amount, 0) },
        { status: 'Pending', count: pending, amount: withdrawals.filter(w => w.status === 'pending').reduce((sum, w) => sum + w.amount, 0) },
        { status: 'Rejected', count: rejected, amount: withdrawals.filter(w => w.status === 'rejected').reduce((sum, w) => sum + w.amount, 0) },
      ],
    },
    charts: [
      {
        title: 'Withdrawal Status Distribution',
        type: 'pie',
        data: {
          labels: ['Approved', 'Pending', 'Rejected'],
          datasets: [{ data: [approved, pending, rejected] }],
        },
      },
    ],
  };
}

/**
 * Generate analytics report
 */
export function generateAnalyticsReport(
  metrics: any
): ReportContent {
  return {
    title: 'Platform Analytics Report',
    generatedAt: new Date(),
    timeRange: 'Last 7 days',
    summary: {
      totalRevenue: metrics.totalRevenue,
      totalTransactions: metrics.totalTransactions,
      successRate: metrics.successRate,
      fraudRate: metrics.fraudRate,
      retrySuccessRate: metrics.retrySuccessRate,
    },
    details: {
      paymentHealth: {
        successRate: metrics.successRate,
        failureRate: metrics.failureRate,
        fraudRate: metrics.fraudRate,
      },
    },
    charts: [
      {
        title: 'Payment Health Metrics',
        type: 'bar',
        data: {
          labels: ['Success', 'Failure', 'Fraud'],
          datasets: [{ data: [metrics.successRate, metrics.failureRate, metrics.fraudRate] }],
        },
      },
    ],
  };
}

/**
 * Export report to CSV
 */
export function exportReportToCSV(report: ReportContent): string {
  const lines: string[] = [];

  // Header
  lines.push(`${report.title}`);
  lines.push(`Generated: ${report.generatedAt.toISOString()}`);
  lines.push(`Time Range: ${report.timeRange}`);
  lines.push('');

  // Summary
  lines.push('SUMMARY');
  Object.entries(report.summary).forEach(([key, value]) => {
    lines.push(`${key},${value}`);
  });
  lines.push('');

  // Details
  if (report.details && Object.keys(report.details).length > 0) {
    lines.push('DETAILS');
    Object.entries(report.details).forEach(([key, value]) => {
      lines.push(`${key}`);
      if (Array.isArray(value)) {
        value.forEach(item => {
          lines.push(JSON.stringify(item));
        });
      }
    });
  }

  return lines.join('\n');
}

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

/**
 * Export report to HTML
 */
export function exportReportToHTML(report: ReportContent): string {
  return `
<!DOCTYPE html>
<html>
<head>
  <title>${report.title}</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 20px; }
    h1 { color: #333; }
    .summary { background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0; }
    table { width: 100%; border-collapse: collapse; margin: 20px 0; }
    th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
    th { background: #4CAF50; color: white; }
  </style>
</head>
<body>
  <h1>${report.title}</h1>
  <p>Generated: ${report.generatedAt.toISOString()}</p>
  <p>Time Range: ${report.timeRange}</p>
  
  <div class="summary">
    <h2>Summary</h2>
    <table>
      <tr>
        ${Object.keys(report.summary).map(key => `<th>${key}</th>`).join('')}
      </tr>
      <tr>
        ${Object.values(report.summary).map(value => `<td>${value}</td>`).join('')}
      </tr>
    </table>
  </div>
  
  <h2>Details</h2>
  <pre>${JSON.stringify(report.details, null, 2)}</pre>
</body>
</html>
  `;
}

/**
 * Schedule report execution
 */
export function scheduleReportExecution(reportId: string): ReportExecution {
  return {
    id: `EXEC-${Date.now()}`,
    reportId,
    startTime: new Date(),
    status: 'pending',
    recordsProcessed: 0,
    fileSize: 0,
  };
}

/**
 * Mark report as processing
 */
export function markAsProcessing(execution: ReportExecution): ReportExecution {
  return {
    ...execution,
    status: 'processing',
  };
}

/**
 * Mark report as completed
 */
export function markAsCompleted(
  execution: ReportExecution,
  recordsProcessed: number,
  fileSize: number,
  downloadUrl: string
): ReportExecution {
  return {
    ...execution,
    status: 'completed',
    endTime: new Date(),
    recordsProcessed,
    fileSize,
    downloadUrl,
  };
}

/**
 * Mark report as failed
 */
export function markAsFailed(execution: ReportExecution, error: string): ReportExecution {
  return {
    ...execution,
    status: 'failed',
    endTime: new Date(),
    error,
  };
}

/**
 * Get report execution history
 */
export function getReportExecutionHistory(
  executions: ReportExecution[],
  reportId: string,
  limit: number = 10
): ReportExecution[] {
  return executions
    .filter(e => e.reportId === reportId)
    .sort((a, b) => b.startTime.getTime() - a.startTime.getTime())
    .slice(0, limit);
}

/**
 * Get reports ready for execution
 */
export function getReportsReadyForExecution(
  reports: ScheduledReport[]
): ScheduledReport[] {
  const now = new Date();

  return reports.filter(report => {
    if (!report.enabled) return false;

    const nextRun = report.nextRun || getNextReportRunTime(report);
    return nextRun <= now;
  });
}

/**
 * Get report statistics
 */
export interface ReportStats {
  totalReports: number;
  enabledReports: number;
  totalExecutions: number;
  successfulExecutions: number;
  failedExecutions: number;
  averageExecutionTime: number;
  totalDataProcessed: number;
}

export function getReportStats(
  reports: ScheduledReport[],
  executions: ReportExecution[]
): ReportStats {
  const enabledReports = reports.filter(r => r.enabled).length;
  const successfulExecutions = executions.filter(e => e.status === 'completed').length;
  const failedExecutions = executions.filter(e => e.status === 'failed').length;

  const executionTimes = executions
    .filter(e => e.endTime)
    .map(e => (e.endTime!.getTime() - e.startTime.getTime()) / 1000);
  const averageExecutionTime =
    executionTimes.length > 0
      ? executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length
      : 0;

  const totalDataProcessed = executions.reduce((sum, e) => sum + e.recordsProcessed, 0);

  return {
    totalReports: reports.length,
    enabledReports,
    totalExecutions: executions.length,
    successfulExecutions,
    failedExecutions,
    averageExecutionTime,
    totalDataProcessed,
  };
}
