/**
 * Leaderboard Service
 *
 * Rep/CSM performance leaderboards for the staff dashboard.
 * Tracks demo-to-close rates, response times, and expansion wins.
 */

import type {
  Leaderboard,
  LeaderboardEntry,
  LeaderboardFilters,
  LeaderboardPeriod,
  RepMetrics,
  TrendDirection,
} from '@/lib/types/experiments.types';

// ============================================================================
// Period Calculation Helpers
// ============================================================================

function getPeriodDates(period: LeaderboardPeriod): {
  start: Date;
  end: Date;
  previousStart: Date;
  previousEnd: Date;
} {
  const now = new Date();
  const end = new Date(now);
  let start: Date;
  let previousStart: Date;
  let previousEnd: Date;

  switch (period) {
    case 'week':
      start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
      previousEnd = new Date(start.getTime() - 1);
      previousStart = new Date(previousEnd.getTime() - 7 * 24 * 60 * 60 * 1000);
      break;
    case 'month':
      start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
      previousEnd = new Date(start.getTime() - 1);
      previousStart = new Date(previousEnd.getTime() - 30 * 24 * 60 * 60 * 1000);
      break;
    case 'quarter':
      start = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);
      previousEnd = new Date(start.getTime() - 1);
      previousStart = new Date(previousEnd.getTime() - 90 * 24 * 60 * 60 * 1000);
      break;
    case 'year':
      start = new Date(now.getTime() - 365 * 24 * 60 * 60 * 1000);
      previousEnd = new Date(start.getTime() - 1);
      previousStart = new Date(previousEnd.getTime() - 365 * 24 * 60 * 60 * 1000);
      break;
    default:
      start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
      previousEnd = new Date(start.getTime() - 1);
      previousStart = new Date(previousEnd.getTime() - 30 * 24 * 60 * 60 * 1000);
  }

  return { start, end, previousStart, previousEnd };
}

function calculateTrend(current: number, previous: number): TrendDirection {
  if (current > previous) return 'up';
  if (current < previous) return 'down';
  return 'same';
}

// ============================================================================
// Leaderboard Data
// ============================================================================

/**
 * Get leaderboard data
 */
export async function getLeaderboard(
  filters: LeaderboardFilters = {}
): Promise<Leaderboard> {
  const period: LeaderboardPeriod = filters.period || 'month';
  const sortBy = filters.sortBy || 'demoToCloseRate';
  const sortOrder = filters.sortOrder || 'desc';
  const limit = filters.limit || 10;

  const dates = getPeriodDates(period);

  // In production, this would query the database for actual rep/CSM data
  // aggregating from demo_bookings, support_tickets, etc.
  // For now, using realistic mock data

  const rawData: Array<{
    id: string;
    name: string;
    email: string;
    avatar?: string;
    role: string;
    currentMetrics: RepMetrics;
    previousMetrics: RepMetrics;
  }> = [
    {
      id: 'staff_1',
      name: 'Ahmed Al-Rashid',
      email: 'ahmed@mawidi.com',
      avatar: undefined,
      role: 'Sales Rep',
      currentMetrics: {
        demosHandled: 45,
        demosConfirmed: 38,
        demoToCloseRate: 42.1,
        avgResponseTimeMinutes: 12,
        expansionWins: 8,
        revenue: 156000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.8,
      },
      previousMetrics: {
        demosHandled: 38,
        demosConfirmed: 30,
        demoToCloseRate: 36.8,
        avgResponseTimeMinutes: 15,
        expansionWins: 5,
        revenue: 120000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.6,
      },
    },
    {
      id: 'staff_2',
      name: 'Sara Mohammed',
      email: 'sara@mawidi.com',
      avatar: undefined,
      role: 'Sales Rep',
      currentMetrics: {
        demosHandled: 52,
        demosConfirmed: 41,
        demoToCloseRate: 38.5,
        avgResponseTimeMinutes: 8,
        expansionWins: 12,
        revenue: 198000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.9,
      },
      previousMetrics: {
        demosHandled: 48,
        demosConfirmed: 40,
        demoToCloseRate: 37.5,
        avgResponseTimeMinutes: 10,
        expansionWins: 9,
        revenue: 168000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.7,
      },
    },
    {
      id: 'staff_3',
      name: 'Omar Hassan',
      email: 'omar@mawidi.com',
      avatar: undefined,
      role: 'CSM',
      currentMetrics: {
        demosHandled: 18,
        demosConfirmed: 15,
        demoToCloseRate: 55.6,
        avgResponseTimeMinutes: 20,
        expansionWins: 15,
        revenue: 234000,
        ticketsResolved: 67,
        avgTicketResolutionHours: 4.2,
        customerSatisfaction: 4.7,
      },
      previousMetrics: {
        demosHandled: 15,
        demosConfirmed: 13,
        demoToCloseRate: 53.3,
        avgResponseTimeMinutes: 25,
        expansionWins: 11,
        revenue: 187000,
        ticketsResolved: 54,
        avgTicketResolutionHours: 5.1,
        customerSatisfaction: 4.5,
      },
    },
    {
      id: 'staff_4',
      name: 'Fatima Al-Qasimi',
      email: 'fatima@mawidi.com',
      avatar: undefined,
      role: 'Sales Rep',
      currentMetrics: {
        demosHandled: 39,
        demosConfirmed: 32,
        demoToCloseRate: 35.9,
        avgResponseTimeMinutes: 14,
        expansionWins: 6,
        revenue: 128000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.6,
      },
      previousMetrics: {
        demosHandled: 42,
        demosConfirmed: 35,
        demoToCloseRate: 38.1,
        avgResponseTimeMinutes: 12,
        expansionWins: 7,
        revenue: 142000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.7,
      },
    },
    {
      id: 'staff_5',
      name: 'Khalid Nasser',
      email: 'khalid@mawidi.com',
      avatar: undefined,
      role: 'CSM',
      currentMetrics: {
        demosHandled: 12,
        demosConfirmed: 10,
        demoToCloseRate: 50.0,
        avgResponseTimeMinutes: 18,
        expansionWins: 9,
        revenue: 178000,
        ticketsResolved: 89,
        avgTicketResolutionHours: 3.8,
        customerSatisfaction: 4.8,
      },
      previousMetrics: {
        demosHandled: 14,
        demosConfirmed: 11,
        demoToCloseRate: 50.0,
        avgResponseTimeMinutes: 22,
        expansionWins: 7,
        revenue: 145000,
        ticketsResolved: 72,
        avgTicketResolutionHours: 4.5,
        customerSatisfaction: 4.6,
      },
    },
    {
      id: 'staff_6',
      name: 'Layla Ibrahim',
      email: 'layla@mawidi.com',
      avatar: undefined,
      role: 'Sales Rep',
      currentMetrics: {
        demosHandled: 31,
        demosConfirmed: 26,
        demoToCloseRate: 32.3,
        avgResponseTimeMinutes: 16,
        expansionWins: 4,
        revenue: 98000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.4,
      },
      previousMetrics: {
        demosHandled: 28,
        demosConfirmed: 22,
        demoToCloseRate: 28.6,
        avgResponseTimeMinutes: 19,
        expansionWins: 3,
        revenue: 78000,
        ticketsResolved: 0,
        avgTicketResolutionHours: 0,
        customerSatisfaction: 4.3,
      },
    },
  ];

  // Sort by the specified metric
  const sortedData = [...rawData].sort((a, b) => {
    const aValue = a.currentMetrics[sortBy] ?? 0;
    const bValue = b.currentMetrics[sortBy] ?? 0;
    return sortOrder === 'desc' ? bValue - aValue : aValue - bValue;
  });

  // Calculate previous ranks for trend
  const previousSorted = [...rawData].sort((a, b) => {
    const aValue = a.previousMetrics[sortBy] ?? 0;
    const bValue = b.previousMetrics[sortBy] ?? 0;
    return sortOrder === 'desc' ? bValue - aValue : aValue - bValue;
  });

  const previousRankMap = new Map<string, number>();
  previousSorted.forEach((item, index) => {
    previousRankMap.set(item.id, index + 1);
  });

  // Build leaderboard entries
  const entries: LeaderboardEntry[] = sortedData.slice(0, limit).map((item, index) => {
    const currentRank = index + 1;
    const previousRank = previousRankMap.get(item.id) || currentRank;
    const rankChange = previousRank - currentRank; // Positive = improved

    return {
      id: item.id,
      name: item.name,
      email: item.email,
      avatar: item.avatar,
      role: item.role,
      metrics: item.currentMetrics,
      rank: currentRank,
      previousRank,
      trend: calculateTrend(currentRank, previousRank) === 'up' ? 'up' :
             calculateTrend(currentRank, previousRank) === 'down' ? 'down' : 'same',
      rankChange,
    };
  });

  // Calculate totals
  const totals = {
    totalDemos: rawData.reduce((sum, r) => sum + r.currentMetrics.demosHandled, 0),
    totalConversions: rawData.reduce(
      (sum, r) =>
        sum + Math.round(r.currentMetrics.demosHandled * (r.currentMetrics.demoToCloseRate / 100)),
      0
    ),
    totalRevenue: rawData.reduce((sum, r) => sum + r.currentMetrics.revenue, 0),
    avgResponseTime:
      Math.round(
        (rawData.reduce((sum, r) => sum + r.currentMetrics.avgResponseTimeMinutes, 0) /
          rawData.length) *
          10
      ) / 10,
    avgTicketResolution:
      Math.round(
        (rawData
          .filter((r) => r.currentMetrics.ticketsResolved > 0)
          .reduce((sum, r) => sum + r.currentMetrics.avgTicketResolutionHours, 0) /
          rawData.filter((r) => r.currentMetrics.ticketsResolved > 0).length || 1) *
          10
      ) / 10,
  };

  return {
    period,
    periodStart: dates.start.toISOString(),
    periodEnd: dates.end.toISOString(),
    previousPeriodStart: dates.previousStart.toISOString(),
    previousPeriodEnd: dates.previousEnd.toISOString(),
    entries,
    totals,
  };
}

/**
 * Get leaderboard summary for quick overview
 */
export async function getLeaderboardSummary(): Promise<{
  topPerformer: string;
  topPerformerRevenue: number;
  totalTeamRevenue: number;
  avgDemoToCloseRate: number;
  avgResponseTime: number;
  totalExpansions: number;
}> {
  const leaderboard = await getLeaderboard({ limit: 100 });

  const topEntry = leaderboard.entries[0];
  const allMetrics = leaderboard.entries.map((e) => e.metrics);

  return {
    topPerformer: topEntry?.name || 'N/A',
    topPerformerRevenue: topEntry?.metrics.revenue || 0,
    totalTeamRevenue: leaderboard.totals.totalRevenue,
    avgDemoToCloseRate:
      Math.round(
        (allMetrics.reduce((sum, m) => sum + m.demoToCloseRate, 0) / allMetrics.length) * 10
      ) / 10,
    avgResponseTime: leaderboard.totals.avgResponseTime,
    totalExpansions: allMetrics.reduce((sum, m) => sum + m.expansionWins, 0),
  };
}

/**
 * Get individual rep/CSM performance details
 */
export async function getRepPerformance(
  repId: string,
  period: LeaderboardPeriod = 'month'
): Promise<LeaderboardEntry | null> {
  const leaderboard = await getLeaderboard({ period, limit: 100 });
  return leaderboard.entries.find((e) => e.id === repId) || null;
}
