import { supabase } from './supabase';
import type { Database } from './database.types';

// Types for analytics data
export interface SalesMetrics {
  totalRevenue: number;
  netRevenue: number;
  platformFees: number;
  ticketsSold: number;
  averageTicketPrice: number;
  conversionRate: number;
  refundRate: number;
}

export interface SalesByTimeframe {
  date: string;
  revenue: number;
  ticketsSold: number;
  averagePrice: number;
}

export interface TicketTypePerformance {
  ticketTypeId: string;
  name: string;
  price: number;
  quantitySold: number;
  quantityAvailable: number;
  revenue: number;
  sellThroughRate: number;
}

export interface RevenueBreakdown {
  grossRevenue: number;
  platformFees: number;
  netRevenue: number;
  stripeFees: number;
  organizerPayout: number;
}

export interface SalesAnalyticsData {
  metrics: SalesMetrics;
  revenueBreakdown: RevenueBreakdown;
  salesByDay: SalesByTimeframe[];
  salesByHour: SalesByTimeframe[];
  ticketTypePerformance: TicketTypePerformance[];
  topSellingTickets: TicketTypePerformance[];
  recentSales: any[];
}

// Analytics calculation functions
export class EventAnalytics {
  private eventId: string;

  constructor(eventId: string) {
    this.eventId = eventId;
  }

  // Get comprehensive analytics data for an event
  async getAnalyticsData(): Promise<SalesAnalyticsData> {
    const [
      metrics,
      revenueBreakdown,
      salesByDay,
      salesByHour,
      ticketTypePerformance,
      recentSales
    ] = await Promise.all([
      this.getSalesMetrics(),
      this.getRevenueBreakdown(),
      this.getSalesByTimeframe('day'),
      this.getSalesByTimeframe('hour'),
      this.getTicketTypePerformance(),
      this.getRecentSales()
    ]);

    return {
      metrics,
      revenueBreakdown,
      salesByDay,
      salesByHour,
      ticketTypePerformance,
      topSellingTickets: ticketTypePerformance.sort((a, b) => b.quantitySold - a.quantitySold).slice(0, 5),
      recentSales
    };
  }

  // Calculate key sales metrics
  async getSalesMetrics(): Promise<SalesMetrics> {
    try {
      // Get ticket sales data
      const { data: tickets, error: ticketsError } = await supabase
        .from('tickets')
        .select(`
          id,
          price,
          platform_fee_charged,
          created_at,
          ticket_types!inner(
            event_id
          )
        `)
        .eq('ticket_types.event_id', this.eventId);

      if (ticketsError) throw ticketsError;

      // Get ticket types for total capacity
      const { data: ticketTypes, error: typesError } = await supabase
        .from('ticket_types')
        .select('quantity_available')
        .eq('event_id', this.eventId);

      if (typesError) throw typesError;

      const ticketsSold = tickets?.length || 0;
      const totalCapacity = ticketTypes?.reduce((sum, type) => sum + (type.quantity_available || 0), 0) || 0;
      const totalRevenue = tickets?.reduce((sum, ticket) => sum + (ticket.price || 0), 0) || 0;
      const platformFees = tickets?.reduce((sum, ticket) => sum + (ticket.platform_fee_charged || 0), 0) || 0;
      const netRevenue = totalRevenue - platformFees;
      const averageTicketPrice = ticketsSold > 0 ? totalRevenue / ticketsSold : 0;
      const conversionRate = totalCapacity > 0 ? (ticketsSold / totalCapacity) * 100 : 0;

      return {
        totalRevenue,
        netRevenue,
        platformFees,
        ticketsSold,
        averageTicketPrice,
        conversionRate,
        refundRate: 0 // TODO: Implement refunds tracking
      };
    } catch (error) {
      console.error('Error calculating sales metrics:', error);
      return {
        totalRevenue: 0,
        netRevenue: 0,
        platformFees: 0,
        ticketsSold: 0,
        averageTicketPrice: 0,
        conversionRate: 0,
        refundRate: 0
      };
    }
  }

  // Get detailed revenue breakdown
  async getRevenueBreakdown(): Promise<RevenueBreakdown> {
    try {
      const { data: tickets, error } = await supabase
        .from('tickets')
        .select(`
          price,
          platform_fee_charged,
          stripe_fee_charged,
          ticket_types!inner(
            event_id
          )
        `)
        .eq('ticket_types.event_id', this.eventId);

      if (error) throw error;

      const grossRevenue = tickets?.reduce((sum, ticket) => sum + (ticket.price || 0), 0) || 0;
      const platformFees = tickets?.reduce((sum, ticket) => sum + (ticket.platform_fee_charged || 0), 0) || 0;
      const stripeFees = tickets?.reduce((sum, ticket) => sum + (ticket.stripe_fee_charged || 0), 0) || 0;
      const netRevenue = grossRevenue - platformFees;
      const organizerPayout = grossRevenue - platformFees - stripeFees;

      return {
        grossRevenue,
        platformFees,
        netRevenue,
        stripeFees,
        organizerPayout
      };
    } catch (error) {
      console.error('Error calculating revenue breakdown:', error);
      return {
        grossRevenue: 0,
        platformFees: 0,
        netRevenue: 0,
        stripeFees: 0,
        organizerPayout: 0
      };
    }
  }

  // Get sales data grouped by timeframe (day or hour)
  async getSalesByTimeframe(timeframe: 'day' | 'hour'): Promise<SalesByTimeframe[]> {
    try {
      const dateFormat = timeframe === 'day' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH24:00:00';
      
      const { data, error } = await supabase
        .from('tickets')
        .select(`
          price,
          created_at,
          ticket_types!inner(
            event_id
          )
        `)
        .eq('ticket_types.event_id', this.eventId);

      if (error) throw error;

      // Group sales by timeframe
      const salesMap = new Map<string, { revenue: number; count: number }>();
      
      tickets?.forEach(ticket => {
        const date = new Date(ticket.created_at);
        let key: string;
        
        if (timeframe === 'day') {
          key = date.toISOString().split('T')[0];
        } else {
          key = `${date.toISOString().split('T')[0]} ${date.getHours().toString().padStart(2, '0')}:00:00`;
        }
        
        const existing = salesMap.get(key) || { revenue: 0, count: 0 };
        salesMap.set(key, {
          revenue: existing.revenue + (ticket.price || 0),
          count: existing.count + 1
        });
      });

      // Convert to array and sort by date
      return Array.from(salesMap.entries())
        .map(([date, data]) => ({
          date,
          revenue: data.revenue,
          ticketsSold: data.count,
          averagePrice: data.count > 0 ? data.revenue / data.count : 0
        }))
        .sort((a, b) => a.date.localeCompare(b.date));
    } catch (error) {
      console.error('Error getting sales by timeframe:', error);
      return [];
    }
  }

  // Get performance metrics for each ticket type
  async getTicketTypePerformance(): Promise<TicketTypePerformance[]> {
    try {
      // Get ticket types with sales data
      const { data: ticketTypes, error: typesError } = await supabase
        .from('ticket_types')
        .select(`
          id,
          name,
          price,
          quantity_available,
          tickets(id, price)
        `)
        .eq('event_id', this.eventId);

      if (typesError) throw typesError;

      return ticketTypes?.map(type => {
        const quantitySold = type.tickets?.length || 0;
        const revenue = type.tickets?.reduce((sum: number, ticket: any) => sum + (ticket.price || 0), 0) || 0;
        const sellThroughRate = type.quantity_available > 0 ? (quantitySold / type.quantity_available) * 100 : 0;

        return {
          ticketTypeId: type.id,
          name: type.name,
          price: type.price || 0,
          quantitySold,
          quantityAvailable: type.quantity_available || 0,
          revenue,
          sellThroughRate
        };
      }) || [];
    } catch (error) {
      console.error('Error getting ticket type performance:', error);
      return [];
    }
  }

  // Get recent sales transactions
  async getRecentSales(limit: number = 20): Promise<any[]> {
    try {
      const { data: tickets, error } = await supabase
        .from('tickets')
        .select(`
          id,
          price,
          purchaser_name,
          purchaser_email,
          created_at,
          ticket_types!inner(
            event_id,
            name
          )
        `)
        .eq('ticket_types.event_id', this.eventId)
        .order('created_at', { ascending: false })
        .limit(limit);

      if (error) throw error;

      return tickets || [];
    } catch (error) {
      console.error('Error getting recent sales:', error);
      return [];
    }
  }

  // Get sales velocity (sales per hour/day trends)
  async getSalesVelocity(): Promise<{ current: number; trend: 'up' | 'down' | 'stable' }> {
    try {
      const now = new Date();
      const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
      const twoDaysAgo = new Date(now.getTime() - 48 * 60 * 60 * 1000);

      const { data: recentSales, error: recentError } = await supabase
        .from('tickets')
        .select(`
          id,
          created_at,
          ticket_types!inner(event_id)
        `)
        .eq('ticket_types.event_id', this.eventId)
        .gte('created_at', oneDayAgo.toISOString());

      const { data: previousSales, error: previousError } = await supabase
        .from('tickets')
        .select(`
          id,
          created_at,
          ticket_types!inner(event_id)
        `)
        .eq('ticket_types.event_id', this.eventId)
        .gte('created_at', twoDaysAgo.toISOString())
        .lt('created_at', oneDayAgo.toISOString());

      if (recentError || previousError) throw recentError || previousError;

      const currentVelocity = recentSales?.length || 0;
      const previousVelocity = previousSales?.length || 0;

      let trend: 'up' | 'down' | 'stable' = 'stable';
      if (currentVelocity > previousVelocity * 1.1) trend = 'up';
      else if (currentVelocity < previousVelocity * 0.9) trend = 'down';

      return { current: currentVelocity, trend };
    } catch (error) {
      console.error('Error calculating sales velocity:', error);
      return { current: 0, trend: 'stable' };
    }
  }

  // Format currency values
  static formatCurrency(amount: number): string {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD'
    }).format(amount);
  }

  // Format percentage values
  static formatPercentage(value: number): string {
    return `${value.toFixed(1)}%`;
  }

  // Format large numbers
  static formatNumber(value: number): string {
    if (value >= 1000000) {
      return `${(value / 1000000).toFixed(1)}M`;
    } else if (value >= 1000) {
      return `${(value / 1000).toFixed(1)}K`;
    }
    return value.toString();
  }
}

// Export data to CSV
export function exportAnalyticsToCSV(data: SalesAnalyticsData, eventTitle: string): void {
  const csvContent = [
    // Summary metrics
    ['Sales Analytics Report', eventTitle],
    ['Generated', new Date().toISOString()],
    [''],
    ['SUMMARY METRICS'],
    ['Total Revenue', EventAnalytics.formatCurrency(data.metrics.totalRevenue)],
    ['Net Revenue', EventAnalytics.formatCurrency(data.metrics.netRevenue)],
    ['Platform Fees', EventAnalytics.formatCurrency(data.metrics.platformFees)],
    ['Tickets Sold', data.metrics.ticketsSold.toString()],
    ['Average Ticket Price', EventAnalytics.formatCurrency(data.metrics.averageTicketPrice)],
    ['Conversion Rate', EventAnalytics.formatPercentage(data.metrics.conversionRate)],
    [''],
    ['TICKET TYPE PERFORMANCE'],
    ['Ticket Type', 'Price', 'Sold', 'Available', 'Revenue', 'Sell-through Rate'],
    ...data.ticketTypePerformance.map(type => [
      type.name,
      EventAnalytics.formatCurrency(type.price),
      type.quantitySold.toString(),
      type.quantityAvailable.toString(),
      EventAnalytics.formatCurrency(type.revenue),
      EventAnalytics.formatPercentage(type.sellThroughRate)
    ]),
    [''],
    ['DAILY SALES'],
    ['Date', 'Revenue', 'Tickets Sold', 'Average Price'],
    ...data.salesByDay.map(day => [
      day.date,
      EventAnalytics.formatCurrency(day.revenue),
      day.ticketsSold.toString(),
      EventAnalytics.formatCurrency(day.averagePrice)
    ])
  ];

  const csv = csvContent.map(row => row.join(',')).join('\n');
  const blob = new Blob([csv], { type: 'text/csv' });
  const url = window.URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = `${eventTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase()}_analytics_${new Date().toISOString().split('T')[0]}.csv`;
  link.click();
  window.URL.revokeObjectURL(url);
}