/**
 * Provider Revenue Analytics Service
 * Tracks provider revenue, commissions, and payout scheduling
 */

export interface ProviderRevenue {
  providerId: string;
  providerName: string;
  period: string; // YYYY-MM
  totalRevenue: number;
  gameCount: number;
  totalPlays: number;
  totalWins: number;
  totalLosses: number;
  houseEdge: number;
  commissionRate: number;
  commissionAmount: number;
  netRevenue: number;
  lastUpdated: Date;
}

export interface Commission {
  id: string;
  providerId: string;
  providerName: string;
  period: string;
  amount: number;
  rate: number;
  status: 'pending' | 'scheduled' | 'paid' | 'failed';
  scheduledPayoutDate: Date;
  actualPayoutDate?: Date;
  paymentMethod: string;
  transactionId?: string;
  notes?: string;
}

export interface PayoutSchedule {
  providerId: string;
  providerName: string;
  frequency: 'weekly' | 'biweekly' | 'monthly';
  nextPayoutDate: Date;
  bankAccount: string;
  paymentMethod: 'bank_transfer' | 'wire' | 'check' | 'crypto';
  minimumThreshold: number;
  isActive: boolean;
}

// In-memory storage
const revenues = new Map<string, ProviderRevenue[]>();
const commissions = new Map<string, Commission[]>();
const payoutSchedules = new Map<string, PayoutSchedule>();

const DEFAULT_COMMISSION_RATE = 0.30; // 30%

export async function recordProviderRevenue(revenue: ProviderRevenue): Promise<void> {
  const key = `${revenue.providerId}_${revenue.period}`;
  
  // Calculate commission
  revenue.commissionAmount = revenue.totalRevenue * revenue.commissionRate;
  revenue.netRevenue = revenue.totalRevenue - revenue.commissionAmount;

  const providerRevenues = revenues.get(revenue.providerId) || [];
  providerRevenues.push(revenue);
  revenues.set(revenue.providerId, providerRevenues);
}

export async function getProviderRevenue(
  providerId: string,
  startPeriod?: string,
  endPeriod?: string
): Promise<ProviderRevenue[]> {
  const providerRevenues = revenues.get(providerId) || [];

  if (!startPeriod || !endPeriod) {
    return providerRevenues;
  }

  return providerRevenues.filter((r) => r.period >= startPeriod && r.period <= endPeriod);
}

export async function calculateProviderStats(providerId: string): Promise<{
  totalRevenue: number;
  totalCommissions: number;
  avgCommissionRate: number;
  gameCount: number;
  totalPlays: number;
  houseEdge: number;
}> {
  const providerRevenues = revenues.get(providerId) || [];

  if (providerRevenues.length === 0) {
    return {
      totalRevenue: 0,
      totalCommissions: 0,
      avgCommissionRate: 0,
      gameCount: 0,
      totalPlays: 0,
      houseEdge: 0,
    };
  }

  const totalRevenue = providerRevenues.reduce((sum, r) => sum + r.totalRevenue, 0);
  const totalCommissions = providerRevenues.reduce((sum, r) => sum + r.commissionAmount, 0);
  const avgCommissionRate =
    providerRevenues.reduce((sum, r) => sum + r.commissionRate, 0) / providerRevenues.length;
  const gameCount = providerRevenues[providerRevenues.length - 1]?.gameCount || 0;
  const totalPlays = providerRevenues.reduce((sum, r) => sum + r.totalPlays, 0);
  const houseEdge =
    providerRevenues.reduce((sum, r) => sum + r.houseEdge, 0) / providerRevenues.length;

  return {
    totalRevenue,
    totalCommissions,
    avgCommissionRate,
    gameCount,
    totalPlays,
    houseEdge,
  };
}

export async function createCommission(
  providerId: string,
  providerName: string,
  period: string,
  amount: number,
  rate: number
): Promise<Commission> {
  const commission: Commission = {
    id: `commission_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
    providerId,
    providerName,
    period,
    amount,
    rate,
    status: 'pending',
    scheduledPayoutDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days
    paymentMethod: 'bank_transfer',
  };

  const providerCommissions = commissions.get(providerId) || [];
  providerCommissions.push(commission);
  commissions.set(providerId, providerCommissions);

  return commission;
}

export async function getProviderCommissions(providerId: string): Promise<Commission[]> {
  return commissions.get(providerId) || [];
}

export async function scheduleCommissionPayout(
  commissionId: string,
  payoutDate: Date
): Promise<Commission> {
  for (const [, comms] of commissions) {
    const commission = comms.find((c) => c.id === commissionId);
    if (commission) {
      commission.status = 'scheduled';
      commission.scheduledPayoutDate = payoutDate;
      return commission;
    }
  }

  throw new Error('Commission not found');
}

export async function recordCommissionPayout(
  commissionId: string,
  transactionId: string,
  payoutDate: Date
): Promise<Commission> {
  for (const [, comms] of commissions) {
    const commission = comms.find((c) => c.id === commissionId);
    if (commission) {
      commission.status = 'paid';
      commission.transactionId = transactionId;
      commission.actualPayoutDate = payoutDate;
      return commission;
    }
  }

  throw new Error('Commission not found');
}

export async function setupPayoutSchedule(schedule: PayoutSchedule): Promise<void> {
  payoutSchedules.set(schedule.providerId, schedule);
}

export async function getPayoutSchedule(providerId: string): Promise<PayoutSchedule | null> {
  return payoutSchedules.get(providerId) || null;
}

export async function getUpcomingPayouts(): Promise<Commission[]> {
  const upcoming: Commission[] = [];
  const now = new Date();

  for (const [, comms] of commissions) {
    for (const commission of comms) {
      if (
        commission.status === 'scheduled' &&
        commission.scheduledPayoutDate > now &&
        commission.scheduledPayoutDate <= new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000)
      ) {
        upcoming.push(commission);
      }
    }
  }

  return upcoming.sort((a, b) => a.scheduledPayoutDate.getTime() - b.scheduledPayoutDate.getTime());
}

export async function getRevenueReport(
  startPeriod: string,
  endPeriod: string
): Promise<{
  totalRevenue: number;
  totalCommissions: number;
  totalPayouts: number;
  providers: ProviderRevenue[];
  topProviders: Array<{ name: string; revenue: number; commission: number }>;
}> {
  const allRevenues: ProviderRevenue[] = [];
  let totalRevenue = 0;
  let totalCommissions = 0;

  for (const [, providerRevenues] of revenues) {
    const filtered = providerRevenues.filter((r) => r.period >= startPeriod && r.period <= endPeriod);
    allRevenues.push(...filtered);
    totalRevenue += filtered.reduce((sum, r) => sum + r.totalRevenue, 0);
    totalCommissions += filtered.reduce((sum, r) => sum + r.commissionAmount, 0);
  }

  let totalPayouts = 0;
  for (const [, comms] of commissions) {
    totalPayouts += comms
      .filter((c) => c.status === 'paid' && c.period >= startPeriod && c.period <= endPeriod)
      .reduce((sum, c) => sum + c.amount, 0);
  }

  const topProviders = Array.from(revenues.entries())
    .map(([name, revs]) => {
      const filtered = revs.filter((r) => r.period >= startPeriod && r.period <= endPeriod);
      return {
        name,
        revenue: filtered.reduce((sum, r) => sum + r.totalRevenue, 0),
        commission: filtered.reduce((sum, r) => sum + r.commissionAmount, 0),
      };
    })
    .sort((a, b) => b.revenue - a.revenue)
    .slice(0, 10);

  return {
    totalRevenue,
    totalCommissions,
    totalPayouts,
    providers: allRevenues,
    topProviders,
  };
}

export async function getCommissionStats(): Promise<{
  totalPending: number;
  totalScheduled: number;
  totalPaid: number;
  totalFailed: number;
  pendingAmount: number;
  paidAmount: number;
}> {
  let totalPending = 0;
  let totalScheduled = 0;
  let totalPaid = 0;
  let totalFailed = 0;
  let pendingAmount = 0;
  let paidAmount = 0;

  for (const [, comms] of commissions) {
    for (const commission of comms) {
      if (commission.status === 'pending') {
        totalPending++;
        pendingAmount += commission.amount;
      } else if (commission.status === 'scheduled') {
        totalScheduled++;
        pendingAmount += commission.amount;
      } else if (commission.status === 'paid') {
        totalPaid++;
        paidAmount += commission.amount;
      } else if (commission.status === 'failed') {
        totalFailed++;
      }
    }
  }

  return {
    totalPending,
    totalScheduled,
    totalPaid,
    totalFailed,
    pendingAmount,
    paidAmount,
  };
}
