/**
 * Service d'analytiques avancées pour MediFlash SOS+
 * Reporting et insights business en temps réel
 */

export interface AnalyticsData {
  timeframe: TimeFrame;
  metrics: BusinessMetrics;
  trends: TrendData[];
  insights: InsightData[];
  alerts: AlertData[];
  comparisons: ComparisonData;
}

export interface BusinessMetrics {
  // Métriques principales
  totalOrders: MetricValue;
  revenue: MetricValue;
  activeUsers: MetricValue;
  averageDeliveryTime: MetricValue;
  customerSatisfaction: MetricValue;
  
  // Métriques opérationnelles
  fulfillmentRate: MetricValue;
  responseTime: MetricValue;
  cancelationRate: MetricValue;
  repeatCustomerRate: MetricValue;
  
  // Métriques financières
  averageOrderValue: MetricValue;
  profitMargin: MetricValue;
  revenuePerUser: MetricValue;
  
  // Métriques de performance
  systemUptime: MetricValue;
  errorRate: MetricValue;
  apiLatency: MetricValue;
}

export interface MetricValue {
  current: number;
  previous: number;
  change: number; // pourcentage de changement
  changeType: 'increase' | 'decrease' | 'stable';
  target?: number;
  unit: string;
  format: 'number' | 'percentage' | 'currency' | 'time' | 'rating';
}

export interface TrendData {
  metric: string;
  period: 'hour' | 'day' | 'week' | 'month';
  data: TimeSeriesPoint[];
  forecast?: TimeSeriesPoint[];
  seasonality?: SeasonalPattern;
}

export interface TimeSeriesPoint {
  timestamp: Date;
  value: number;
  metadata?: Record<string, any>;
}

export interface InsightData {
  id: string;
  type: 'opportunity' | 'warning' | 'trend' | 'anomaly';
  priority: 'low' | 'medium' | 'high' | 'critical';
  title: string;
  description: string;
  impact: number; // 1-10
  confidence: number; // 0-1
  recommendations: string[];
  dataPoints: InsightDataPoint[];
  createdAt: Date;
}

export interface AlertData {
  id: string;
  type: 'performance' | 'business' | 'technical' | 'regulatory';
  severity: 'info' | 'warning' | 'error' | 'critical';
  message: string;
  details: string;
  threshold?: number;
  currentValue?: number;
  affectedMetrics: string[];
  suggestedActions: string[];
  timestamp: Date;
  resolved?: boolean;
}

export interface ComparisonData {
  periods: PeriodComparison[];
  competitors?: CompetitorData[];
  benchmarks: BenchmarkData[];
}

export interface TimeFrame {
  start: Date;
  end: Date;
  granularity: 'minute' | 'hour' | 'day' | 'week' | 'month';
  timezone: string;
}

export interface SeasonalPattern {
  type: 'daily' | 'weekly' | 'monthly' | 'yearly';
  peaks: number[];
  troughs: number[];
  strength: number; // 0-1
}

export interface InsightDataPoint {
  metric: string;
  value: number;
  context: string;
}

export interface PeriodComparison {
  name: string;
  timeframe: TimeFrame;
  metrics: Partial<BusinessMetrics>;
  changeFromPrevious: number;
}

export interface CompetitorData {
  name: string;
  marketShare: number;
  averageDeliveryTime: number;
  customerRating: number;
  pricing: number;
}

export interface BenchmarkData {
  metric: string;
  industry: string;
  percentile25: number;
  percentile50: number;
  percentile75: number;
  percentile90: number;
  ourValue: number;
  ranking: number;
}

export interface DashboardConfig {
  userId: string;
  role: 'admin' | 'pharmacy' | 'courier' | 'client';
  widgets: WidgetConfig[];
  refreshInterval: number;
  autoRefresh: boolean;
}

export interface WidgetConfig {
  id: string;
  type: 'metric' | 'chart' | 'table' | 'map' | 'alert';
  size: 'small' | 'medium' | 'large';
  position: { x: number; y: number };
  config: Record<string, any>;
}

export class AnalyticsService {
  private cache = new Map<string, { data: any; expiry: number }>();
  private readonly CACHE_TTL = 5 * 60 * 1000; // 5 minutes

  constructor() {}

  /**
   * Récupère les données analytiques complètes
   */
  async getAnalyticsData(timeframe: TimeFrame, role?: string): Promise<AnalyticsData> {
    const cacheKey = `analytics_${timeframe.start.getTime()}_${timeframe.end.getTime()}_${role}`;
    
    // Vérifier le cache
    const cached = this.cache.get(cacheKey);
    if (cached && cached.expiry > Date.now()) {
      return cached.data;
    }

    try {
      // Récupérer les données en parallèle
      const [metrics, trends, insights, alerts, comparisons] = await Promise.all([
        this.getBusinessMetrics(timeframe, role),
        this.getTrendData(timeframe, role),
        this.getInsights(timeframe, role),
        this.getAlerts(role),
        this.getComparisonData(timeframe, role)
      ]);

      const analyticsData: AnalyticsData = {
        timeframe,
        metrics,
        trends,
        insights,
        alerts,
        comparisons
      };

      // Mettre en cache
      this.cache.set(cacheKey, {
        data: analyticsData,
        expiry: Date.now() + this.CACHE_TTL
      });

      return analyticsData;

    } catch (error) {
      console.error('Error fetching analytics data:', error);
      throw new Error('Erreur lors de la récupération des données analytiques');
    }
  }

  /**
   * Récupère les métriques business principales
   */
  async getBusinessMetrics(timeframe: TimeFrame, role?: string): Promise<BusinessMetrics> {
    // Simulation - en production, récupérer depuis l'API
    const previousPeriod = this.calculatePreviousPeriod(timeframe);
    
    return {
      totalOrders: {
        current: 1247,
        previous: 1089,
        change: 14.5,
        changeType: 'increase',
        target: 1300,
        unit: 'commandes',
        format: 'number'
      },
      revenue: {
        current: 8945000,
        previous: 7823000,
        change: 14.3,
        changeType: 'increase',
        target: 10000000,
        unit: 'FCFA',
        format: 'currency'
      },
      activeUsers: {
        current: 3456,
        previous: 3201,
        change: 8.0,
        changeType: 'increase',
        unit: 'utilisateurs',
        format: 'number'
      },
      averageDeliveryTime: {
        current: 32,
        previous: 38,
        change: -15.8,
        changeType: 'decrease',
        target: 30,
        unit: 'minutes',
        format: 'time'
      },
      customerSatisfaction: {
        current: 4.6,
        previous: 4.4,
        change: 4.5,
        changeType: 'increase',
        target: 4.7,
        unit: '/5',
        format: 'rating'
      },
      fulfillmentRate: {
        current: 0.94,
        previous: 0.91,
        change: 3.3,
        changeType: 'increase',
        target: 0.96,
        unit: '%',
        format: 'percentage'
      },
      responseTime: {
        current: 4.2,
        previous: 5.1,
        change: -17.6,
        changeType: 'decrease',
        target: 3.0,
        unit: 'minutes',
        format: 'time'
      },
      cancelationRate: {
        current: 0.06,
        previous: 0.09,
        change: -33.3,
        changeType: 'decrease',
        target: 0.05,
        unit: '%',
        format: 'percentage'
      },
      repeatCustomerRate: {
        current: 0.68,
        previous: 0.62,
        change: 9.7,
        changeType: 'increase',
        target: 0.75,
        unit: '%',
        format: 'percentage'
      },
      averageOrderValue: {
        current: 7180,
        previous: 7040,
        change: 2.0,
        changeType: 'increase',
        unit: 'FCFA',
        format: 'currency'
      },
      profitMargin: {
        current: 0.23,
        previous: 0.21,
        change: 9.5,
        changeType: 'increase',
        target: 0.25,
        unit: '%',
        format: 'percentage'
      },
      revenuePerUser: {
        current: 2589,
        previous: 2445,
        change: 5.9,
        changeType: 'increase',
        unit: 'FCFA',
        format: 'currency'
      },
      systemUptime: {
        current: 0.997,
        previous: 0.995,
        change: 0.2,
        changeType: 'increase',
        target: 0.999,
        unit: '%',
        format: 'percentage'
      },
      errorRate: {
        current: 0.012,
        previous: 0.018,
        change: -33.3,
        changeType: 'decrease',
        target: 0.01,
        unit: '%',
        format: 'percentage'
      },
      apiLatency: {
        current: 145,
        previous: 167,
        change: -13.2,
        changeType: 'decrease',
        target: 120,
        unit: 'ms',
        format: 'time'
      }
    };
  }

  /**
   * Récupère les données de tendances
   */
  async getTrendData(timeframe: TimeFrame, role?: string): Promise<TrendData[]> {
    const trends: TrendData[] = [
      {
        metric: 'orders',
        period: 'day',
        data: this.generateTimeSeriesData(timeframe, 'orders'),
        forecast: this.generateForecastData(timeframe, 'orders'),
        seasonality: {
          type: 'daily',
          peaks: [12, 19], // 12h et 19h
          troughs: [4, 8], // 4h et 8h
          strength: 0.75
        }
      },
      {
        metric: 'revenue',
        period: 'day',
        data: this.generateTimeSeriesData(timeframe, 'revenue'),
        forecast: this.generateForecastData(timeframe, 'revenue')
      },
      {
        metric: 'deliveryTime',
        period: 'hour',
        data: this.generateTimeSeriesData(timeframe, 'deliveryTime'),
        seasonality: {
          type: 'daily',
          peaks: [18, 20], // Heures de pointe
          troughs: [2, 6], // Heures creuses
          strength: 0.6
        }
      }
    ];

    return trends;
  }

  /**
   * Génère des insights basés sur les données
   */
  async getInsights(timeframe: TimeFrame, role?: string): Promise<InsightData[]> {
    const insights: InsightData[] = [
      {
        id: 'insight_001',
        type: 'opportunity',
        priority: 'high',
        title: 'Potentiel d\'amélioration du temps de livraison',
        description: 'L\'analyse des routes montre qu\'une optimisation des trajets pourrait réduire le temps de livraison de 15%',
        impact: 8,
        confidence: 0.87,
        recommendations: [
          'Implémenter l\'algorithme de routage optimisé',
          'Former les livreurs aux raccourcis locaux',
          'Négocier avec plus de pharmacies centrales'
        ],
        dataPoints: [
          { metric: 'averageDeliveryTime', value: 32, context: 'Temps moyen actuel' },
          { metric: 'potentialImprovement', value: 27, context: 'Temps optimisé possible' }
        ],
        createdAt: new Date()
      },
      {
        id: 'insight_002',
        type: 'trend',
        priority: 'medium',
        title: 'Croissance des commandes urgentes',
        description: 'Les commandes marquées comme "urgentes" ont augmenté de 45% ce mois-ci',
        impact: 6,
        confidence: 0.93,
        recommendations: [
          'Augmenter le personnel de garde',
          'Négocier des tarifs préférentiels pour urgences',
          'Développer des partenariats avec plus de pharmacies 24h/24'
        ],
        dataPoints: [
          { metric: 'urgentOrders', value: 289, context: 'Commandes urgentes ce mois' },
          { metric: 'growth', value: 0.45, context: 'Croissance mensuelle' }
        ],
        createdAt: new Date()
      },
      {
        id: 'insight_003',
        type: 'anomaly',
        priority: 'critical',
        title: 'Pic inhabituel de cancelations',
        description: 'Le taux d\'annulation a augmenté de 300% entre 14h et 16h aujourd\'hui',
        impact: 9,
        confidence: 0.95,
        recommendations: [
          'Investiguer les causes techniques',
          'Contacter les pharmacies affectées',
          'Implémenter des alertes préventives'
        ],
        dataPoints: [
          { metric: 'cancelationRate14h16h', value: 0.24, context: 'Taux entre 14h-16h' },
          { metric: 'normalRate', value: 0.06, context: 'Taux normal' }
        ],
        createdAt: new Date()
      }
    ];

    return insights;
  }

  /**
   * Récupère les alertes actives
   */
  async getAlerts(role?: string): Promise<AlertData[]> {
    const alerts: AlertData[] = [
      {
        id: 'alert_001',
        type: 'performance',
        severity: 'warning',
        message: 'Temps de réponse API dégradé',
        details: 'Le temps de réponse moyen de l\'API dépasse le seuil de 200ms',
        threshold: 200,
        currentValue: 245,
        affectedMetrics: ['apiLatency', 'customerSatisfaction'],
        suggestedActions: [
          'Vérifier les performances de la base de données',
          'Optimiser les requêtes lentes',
          'Considérer un scaling horizontal'
        ],
        timestamp: new Date(Date.now() - 30 * 60 * 1000), // 30 min ago
        resolved: false
      },
      {
        id: 'alert_002',
        type: 'business',
        severity: 'info',
        message: 'Objectif de revenus atteint',
        details: 'Le chiffre d\'affaires mensuel a dépassé l\'objectif de 8M FCFA',
        threshold: 8000000,
        currentValue: 8945000,
        affectedMetrics: ['revenue'],
        suggestedActions: [
          'Célébrer l\'équipe',
          'Réviser les objectifs à la hausse',
          'Analyser les facteurs de succès'
        ],
        timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2h ago
        resolved: false
      }
    ];

    return alerts;
  }

  /**
   * Données de comparaison
   */
  async getComparisonData(timeframe: TimeFrame, role?: string): Promise<ComparisonData> {
    const previousMonth = this.calculatePreviousPeriod(timeframe);
    const lastYear = this.calculateYearOverYear(timeframe);

    return {
      periods: [
        {
          name: 'Mois précédent',
          timeframe: previousMonth,
          metrics: {
            totalOrders: {
              current: 1089,
              previous: 945,
              change: 15.2,
              changeType: 'increase',
              unit: 'commandes',
              format: 'number'
            }
          },
          changeFromPrevious: 15.2
        },
        {
          name: 'Même période année dernière',
          timeframe: lastYear,
          metrics: {
            totalOrders: {
              current: 756,
              previous: 698,
              change: 8.3,
              changeType: 'increase',
              unit: 'commandes',
              format: 'number'
            }
          },
          changeFromPrevious: 65.0
        }
      ],
      benchmarks: [
        {
          metric: 'deliveryTime',
          industry: 'Livraison médicale',
          percentile25: 45,
          percentile50: 35,
          percentile75: 25,
          percentile90: 18,
          ourValue: 32,
          ranking: 65
        },
        {
          metric: 'customerSatisfaction',
          industry: 'E-commerce Afrique',
          percentile25: 3.8,
          percentile50: 4.2,
          percentile75: 4.5,
          percentile90: 4.8,
          ourValue: 4.6,
          ranking: 80
        }
      ]
    };
  }

  /**
   * Configuration des dashboards personnalisés
   */
  async getDashboardConfig(userId: string, role: string): Promise<DashboardConfig> {
    // En production, récupérer depuis la base de données
    const defaultConfig: DashboardConfig = {
      userId,
      role: role as any,
      refreshInterval: 30000, // 30 secondes
      autoRefresh: true,
      widgets: this.getDefaultWidgets(role)
    };

    return defaultConfig;
  }

  /**
   * Exporter les données
   */
  async exportData(
    timeframe: TimeFrame,
    format: 'csv' | 'xlsx' | 'pdf',
    metrics: string[]
  ): Promise<{ url: string; filename: string }> {
    // Simulation - en production, générer le fichier côté serveur
    const filename = `mediflash_analytics_${timeframe.start.toISOString().split('T')[0]}.${format}`;
    
    return {
      url: `/api/analytics/export/${filename}`,
      filename
    };
  }

  /**
   * Méthodes utilitaires privées
   */

  private calculatePreviousPeriod(timeframe: TimeFrame): TimeFrame {
    const duration = timeframe.end.getTime() - timeframe.start.getTime();
    return {
      start: new Date(timeframe.start.getTime() - duration),
      end: new Date(timeframe.start.getTime()),
      granularity: timeframe.granularity,
      timezone: timeframe.timezone
    };
  }

  private calculateYearOverYear(timeframe: TimeFrame): TimeFrame {
    return {
      start: new Date(timeframe.start.getFullYear() - 1, timeframe.start.getMonth(), timeframe.start.getDate()),
      end: new Date(timeframe.end.getFullYear() - 1, timeframe.end.getMonth(), timeframe.end.getDate()),
      granularity: timeframe.granularity,
      timezone: timeframe.timezone
    };
  }

  private generateTimeSeriesData(timeframe: TimeFrame, metric: string): TimeSeriesPoint[] {
    const points: TimeSeriesPoint[] = [];
    const duration = timeframe.end.getTime() - timeframe.start.getTime();
    const interval = duration / 30; // 30 points de données

    for (let i = 0; i < 30; i++) {
      const timestamp = new Date(timeframe.start.getTime() + (i * interval));
      const baseValue = this.getBaseValueForMetric(metric);
      const variation = (Math.random() - 0.5) * 0.3; // ±15% variation
      const seasonalEffect = this.getSeasonalEffect(timestamp, metric);
      
      points.push({
        timestamp,
        value: Math.max(0, baseValue * (1 + variation + seasonalEffect))
      });
    }

    return points;
  }

  private generateForecastData(timeframe: TimeFrame, metric: string): TimeSeriesPoint[] {
    const points: TimeSeriesPoint[] = [];
    const forecastDays = 7;
    const dayMs = 24 * 60 * 60 * 1000;

    for (let i = 1; i <= forecastDays; i++) {
      const timestamp = new Date(timeframe.end.getTime() + (i * dayMs));
      const baseValue = this.getBaseValueForMetric(metric);
      const trend = 0.02; // 2% de croissance tendancielle
      const confidence = Math.max(0.5, 1 - (i / forecastDays) * 0.5); // Confiance décroissante
      
      points.push({
        timestamp,
        value: baseValue * (1 + trend) * confidence,
        metadata: { forecast: true, confidence }
      });
    }

    return points;
  }

  private getBaseValueForMetric(metric: string): number {
    const baseValues = {
      orders: 45,
      revenue: 320000,
      deliveryTime: 32,
      customerSatisfaction: 4.6
    };

    return baseValues[metric as keyof typeof baseValues] || 100;
  }

  private getSeasonalEffect(timestamp: Date, metric: string): number {
    const hour = timestamp.getHours();
    
    // Effets saisonniers basiques
    if (metric === 'orders') {
      // Plus de commandes aux heures de repas
      if (hour >= 11 && hour <= 13) return 0.3;
      if (hour >= 18 && hour <= 20) return 0.4;
      if (hour >= 2 && hour <= 6) return -0.6;
      return 0;
    }

    if (metric === 'deliveryTime') {
      // Temps de livraison plus long aux heures de pointe
      if (hour >= 7 && hour <= 9) return 0.2;
      if (hour >= 17 && hour <= 19) return 0.3;
      return 0;
    }

    return 0;
  }

  private getDefaultWidgets(role: string): WidgetConfig[] {
    const commonWidgets = [
      {
        id: 'total_orders',
        type: 'metric' as const,
        size: 'small' as const,
        position: { x: 0, y: 0 },
        config: { metric: 'totalOrders' }
      },
      {
        id: 'revenue',
        type: 'metric' as const,
        size: 'small' as const,
        position: { x: 1, y: 0 },
        config: { metric: 'revenue' }
      }
    ];

    const roleSpecificWidgets = {
      admin: [
        {
          id: 'orders_chart',
          type: 'chart' as const,
          size: 'large' as const,
          position: { x: 0, y: 1 },
          config: { chartType: 'line', metric: 'orders' }
        }
      ],
      pharmacy: [
        {
          id: 'my_orders',
          type: 'table' as const,
          size: 'medium' as const,
          position: { x: 0, y: 1 },
          config: { dataSource: 'pharmacyOrders' }
        }
      ],
      courier: [
        {
          id: 'delivery_map',
          type: 'map' as const,
          size: 'large' as const,
          position: { x: 0, y: 1 },
          config: { showRoutes: true }
        }
      ]
    };

    return [
      ...commonWidgets,
      ...(roleSpecificWidgets[role as keyof typeof roleSpecificWidgets] || [])
    ];
  }

  /**
   * API publiques
   */

  formatMetricValue(metric: MetricValue): string {
    const formatter = new Intl.NumberFormat('fr-FR', {
      style: metric.format === 'currency' ? 'currency' : 'decimal',
      currency: 'XOF',
      minimumFractionDigits: metric.format === 'percentage' ? 1 : 0,
      maximumFractionDigits: metric.format === 'currency' ? 0 : 2
    });

    if (metric.format === 'percentage') {
      return `${formatter.format(metric.current * 100)}%`;
    }

    return formatter.format(metric.current) + (metric.unit && metric.format !== 'currency' ? ` ${metric.unit}` : '');
  }

  getChangeIcon(changeType: 'increase' | 'decrease' | 'stable'): string {
    return changeType === 'increase' ? '↗' : changeType === 'decrease' ? '↘' : '→';
  }

  getChangeColor(changeType: 'increase' | 'decrease' | 'stable', isPositive: boolean): string {
    if (changeType === 'stable') return 'text-gray-500';
    
    const isGoodChange = (changeType === 'increase') === isPositive;
    return isGoodChange ? 'text-green-600' : 'text-red-600';
  }

  clearCache(): void {
    this.cache.clear();
  }
}

export const analyticsService = new AnalyticsService();