// Modèles pour les statistiques d'événements (connexions, passages, etc.)
//
// Ces modèles ne sont PAS stockés dans Hive car les données sont récupérées
// à la demande depuis l'API et ne nécessitent pas de persistance locale.

/// Statistiques d'authentification
class AuthStats {
  final int success;
  final int failed;
  final int logout;

  const AuthStats({
    required this.success,
    required this.failed,
    required this.logout,
  });

  factory AuthStats.fromJson(Map<String, dynamic> json) {
    return AuthStats(
      success: _parseInt(json['success']),
      failed: _parseInt(json['failed']),
      logout: _parseInt(json['logout']),
    );
  }

  int get total => success + failed + logout;
}

/// Statistiques de passages
class PassageStats {
  final int created;
  final int updated;
  final int deleted;
  final double amount;

  const PassageStats({
    required this.created,
    required this.updated,
    required this.deleted,
    required this.amount,
  });

  factory PassageStats.fromJson(Map<String, dynamic> json) {
    return PassageStats(
      created: _parseInt(json['created']),
      updated: _parseInt(json['updated']),
      deleted: _parseInt(json['deleted']),
      amount: _parseDouble(json['amount']),
    );
  }

  int get total => created + updated + deleted;
}

/// Statistiques utilisateurs
class UserStats {
  final int created;
  final int updated;
  final int deleted;

  const UserStats({
    required this.created,
    required this.updated,
    required this.deleted,
  });

  factory UserStats.fromJson(Map<String, dynamic> json) {
    return UserStats(
      created: _parseInt(json['created']),
      updated: _parseInt(json['updated']),
      deleted: _parseInt(json['deleted']),
    );
  }

  int get total => created + updated + deleted;
}

/// Statistiques secteurs
class SectorStats {
  final int created;
  final int updated;
  final int deleted;

  const SectorStats({
    required this.created,
    required this.updated,
    required this.deleted,
  });

  factory SectorStats.fromJson(Map<String, dynamic> json) {
    return SectorStats(
      created: _parseInt(json['created']),
      updated: _parseInt(json['updated']),
      deleted: _parseInt(json['deleted']),
    );
  }

  int get total => created + updated + deleted;
}

/// Statistiques Stripe
class StripeStats {
  final int created;
  final int success;
  final int failed;
  final int cancelled;
  final double amount;

  const StripeStats({
    required this.created,
    required this.success,
    required this.failed,
    required this.cancelled,
    required this.amount,
  });

  factory StripeStats.fromJson(Map<String, dynamic> json) {
    return StripeStats(
      created: _parseInt(json['created']),
      success: _parseInt(json['success']),
      failed: _parseInt(json['failed']),
      cancelled: _parseInt(json['cancelled']),
      amount: _parseDouble(json['amount']),
    );
  }

  int get total => created + success + failed + cancelled;
}

/// Statistiques globales d'une journée
class DayStats {
  final AuthStats auth;
  final PassageStats passages;
  final UserStats users;
  final SectorStats sectors;
  final StripeStats stripe;

  const DayStats({
    required this.auth,
    required this.passages,
    required this.users,
    required this.sectors,
    required this.stripe,
  });

  factory DayStats.fromJson(Map<String, dynamic> json) {
    return DayStats(
      auth: AuthStats.fromJson(json['auth'] ?? {}),
      passages: PassageStats.fromJson(json['passages'] ?? {}),
      users: UserStats.fromJson(json['users'] ?? {}),
      sectors: SectorStats.fromJson(json['sectors'] ?? {}),
      stripe: StripeStats.fromJson(json['stripe'] ?? {}),
    );
  }
}

/// Totaux d'une journée
class DayTotals {
  final int events;
  final int uniqueUsers;

  const DayTotals({
    required this.events,
    required this.uniqueUsers,
  });

  factory DayTotals.fromJson(Map<String, dynamic> json) {
    return DayTotals(
      events: _parseInt(json['events']),
      uniqueUsers: _parseInt(json['unique_users']),
    );
  }
}

/// Résumé complet d'une journée (réponse de /stats/summary)
class EventSummary {
  final DateTime date;
  final DayStats stats;
  final DayTotals totals;

  const EventSummary({
    required this.date,
    required this.stats,
    required this.totals,
  });

  factory EventSummary.fromJson(Map<String, dynamic> json) {
    return EventSummary(
      date: DateTime.parse(json['date']),
      stats: DayStats.fromJson(json['stats'] ?? {}),
      totals: DayTotals.fromJson(json['totals'] ?? {}),
    );
  }
}

/// Statistiques d'un type d'événement pour une période
class EventTypeStats {
  final int count;
  final double sumAmount;
  final int uniqueUsers;

  const EventTypeStats({
    required this.count,
    required this.sumAmount,
    required this.uniqueUsers,
  });

  factory EventTypeStats.fromJson(Map<String, dynamic> json) {
    return EventTypeStats(
      count: _parseInt(json['count']),
      sumAmount: _parseDouble(json['sum_amount']),
      uniqueUsers: _parseInt(json['unique_users']),
    );
  }
}

/// Données d'une journée dans les stats quotidiennes
class DailyStatsEntry {
  final DateTime date;
  final Map<String, EventTypeStats> events;
  final int totalCount;
  final double totalAmount;

  const DailyStatsEntry({
    required this.date,
    required this.events,
    required this.totalCount,
    required this.totalAmount,
  });

  factory DailyStatsEntry.fromJson(Map<String, dynamic> json) {
    final eventsJson = json['events'] as Map<String, dynamic>? ?? {};
    final events = <String, EventTypeStats>{};

    for (final entry in eventsJson.entries) {
      events[entry.key] = EventTypeStats.fromJson(entry.value);
    }

    final totals = json['totals'] as Map<String, dynamic>? ?? {};

    return DailyStatsEntry(
      date: DateTime.parse(json['date']),
      events: events,
      totalCount: _parseInt(totals['count']),
      totalAmount: _parseDouble(totals['sum_amount']),
    );
  }
}

/// Réponse des stats quotidiennes (/stats/daily)
class DailyStats {
  final DateTime from;
  final DateTime to;
  final List<DailyStatsEntry> days;

  const DailyStats({
    required this.from,
    required this.to,
    required this.days,
  });

  factory DailyStats.fromJson(Map<String, dynamic> json) {
    final daysJson = json['days'] as List<dynamic>? ?? [];

    return DailyStats(
      from: DateTime.parse(json['from']),
      to: DateTime.parse(json['to']),
      days: daysJson.map((d) => DailyStatsEntry.fromJson(d)).toList(),
    );
  }
}

/// Données d'une semaine dans les stats hebdomadaires
class WeeklyStatsEntry {
  final DateTime weekStart;
  final int weekNumber;
  final int year;
  final Map<String, EventTypeStats> events;
  final int totalCount;
  final double totalAmount;

  const WeeklyStatsEntry({
    required this.weekStart,
    required this.weekNumber,
    required this.year,
    required this.events,
    required this.totalCount,
    required this.totalAmount,
  });

  factory WeeklyStatsEntry.fromJson(Map<String, dynamic> json) {
    final eventsJson = json['events'] as Map<String, dynamic>? ?? {};
    final events = <String, EventTypeStats>{};

    for (final entry in eventsJson.entries) {
      events[entry.key] = EventTypeStats.fromJson(entry.value);
    }

    final totals = json['totals'] as Map<String, dynamic>? ?? {};

    return WeeklyStatsEntry(
      weekStart: DateTime.parse(json['week_start']),
      weekNumber: _parseInt(json['week_number']),
      year: _parseInt(json['year']),
      events: events,
      totalCount: _parseInt(totals['count']),
      totalAmount: _parseDouble(totals['sum_amount']),
    );
  }
}

/// Réponse des stats hebdomadaires (/stats/weekly)
class WeeklyStats {
  final DateTime from;
  final DateTime to;
  final List<WeeklyStatsEntry> weeks;

  const WeeklyStats({
    required this.from,
    required this.to,
    required this.weeks,
  });

  factory WeeklyStats.fromJson(Map<String, dynamic> json) {
    final weeksJson = json['weeks'] as List<dynamic>? ?? [];

    return WeeklyStats(
      from: DateTime.parse(json['from']),
      to: DateTime.parse(json['to']),
      weeks: weeksJson.map((w) => WeeklyStatsEntry.fromJson(w)).toList(),
    );
  }
}

/// Données d'un mois dans les stats mensuelles
class MonthlyStatsEntry {
  final String month; // Format: "2025-01"
  final int year;
  final int monthNumber;
  final Map<String, EventTypeStats> events;
  final int totalCount;
  final double totalAmount;

  const MonthlyStatsEntry({
    required this.month,
    required this.year,
    required this.monthNumber,
    required this.events,
    required this.totalCount,
    required this.totalAmount,
  });

  factory MonthlyStatsEntry.fromJson(Map<String, dynamic> json) {
    final eventsJson = json['events'] as Map<String, dynamic>? ?? {};
    final events = <String, EventTypeStats>{};

    for (final entry in eventsJson.entries) {
      events[entry.key] = EventTypeStats.fromJson(entry.value);
    }

    final totals = json['totals'] as Map<String, dynamic>? ?? {};

    return MonthlyStatsEntry(
      month: json['month'] ?? '',
      year: _parseInt(json['year']),
      monthNumber: _parseInt(json['month_number']),
      events: events,
      totalCount: _parseInt(totals['count']),
      totalAmount: _parseDouble(totals['sum_amount']),
    );
  }
}

/// Réponse des stats mensuelles (/stats/monthly)
class MonthlyStats {
  final int year;
  final List<MonthlyStatsEntry> months;

  const MonthlyStats({
    required this.year,
    required this.months,
  });

  factory MonthlyStats.fromJson(Map<String, dynamic> json) {
    final monthsJson = json['months'] as List<dynamic>? ?? [];

    return MonthlyStats(
      year: _parseInt(json['year']),
      months: monthsJson.map((m) => MonthlyStatsEntry.fromJson(m)).toList(),
    );
  }
}

/// Détail d'un événement individuel
class EventDetail {
  final DateTime timestamp;
  final String event;
  final String? username;
  final String? reason;
  final int? attempt;
  final String? ip;
  final String? platform;
  final String? appVersion;
  final Map<String, dynamic>? extra;

  const EventDetail({
    required this.timestamp,
    required this.event,
    this.username,
    this.reason,
    this.attempt,
    this.ip,
    this.platform,
    this.appVersion,
    this.extra,
  });

  factory EventDetail.fromJson(Map<String, dynamic> json) {
    return EventDetail(
      timestamp: DateTime.parse(json['timestamp']),
      event: json['event'] ?? '',
      username: json['username'],
      reason: json['reason'],
      attempt: json['attempt'] != null ? _parseInt(json['attempt']) : null,
      ip: json['ip'],
      platform: json['platform'],
      appVersion: json['app_version'],
      extra: json,
    );
  }
}

/// Pagination pour les détails
class EventPagination {
  final int total;
  final int limit;
  final int offset;
  final bool hasMore;

  const EventPagination({
    required this.total,
    required this.limit,
    required this.offset,
    required this.hasMore,
  });

  factory EventPagination.fromJson(Map<String, dynamic> json) {
    return EventPagination(
      total: _parseInt(json['total']),
      limit: _parseInt(json['limit']),
      offset: _parseInt(json['offset']),
      hasMore: json['has_more'] == true,
    );
  }
}

/// Réponse des détails d'événements (/stats/details)
class EventDetails {
  final DateTime date;
  final List<EventDetail> events;
  final EventPagination pagination;

  const EventDetails({
    required this.date,
    required this.events,
    required this.pagination,
  });

  factory EventDetails.fromJson(Map<String, dynamic> json) {
    final eventsJson = json['events'] as List<dynamic>? ?? [];

    return EventDetails(
      date: DateTime.parse(json['date']),
      events: eventsJson.map((e) => EventDetail.fromJson(e)).toList(),
      pagination: EventPagination.fromJson(json['pagination'] ?? {}),
    );
  }
}

/// Types d'événements disponibles
class EventTypes {
  final List<String> auth;
  final List<String> passages;
  final List<String> sectors;
  final List<String> users;
  final List<String> entities;
  final List<String> operations;
  final List<String> stripe;

  const EventTypes({
    required this.auth,
    required this.passages,
    required this.sectors,
    required this.users,
    required this.entities,
    required this.operations,
    required this.stripe,
  });

  factory EventTypes.fromJson(Map<String, dynamic> json) {
    return EventTypes(
      auth: _parseStringList(json['auth']),
      passages: _parseStringList(json['passages']),
      sectors: _parseStringList(json['sectors']),
      users: _parseStringList(json['users']),
      entities: _parseStringList(json['entities']),
      operations: _parseStringList(json['operations']),
      stripe: _parseStringList(json['stripe']),
    );
  }

  /// Obtient tous les types d'événements à plat
  List<String> get allTypes => [
    ...auth,
    ...passages,
    ...sectors,
    ...users,
    ...entities,
    ...operations,
    ...stripe,
  ];

  /// Obtient le libellé français d'un type d'événement
  static String getLabel(String eventType) {
    switch (eventType) {
      // Auth
      case 'login_success': return 'Connexion réussie';
      case 'login_failed': return 'Connexion échouée';
      case 'logout': return 'Déconnexion';
      // Passages
      case 'passage_created': return 'Passage créé';
      case 'passage_updated': return 'Passage modifié';
      case 'passage_deleted': return 'Passage supprimé';
      // Sectors
      case 'sector_created': return 'Secteur créé';
      case 'sector_updated': return 'Secteur modifié';
      case 'sector_deleted': return 'Secteur supprimé';
      // Users
      case 'user_created': return 'Utilisateur créé';
      case 'user_updated': return 'Utilisateur modifié';
      case 'user_deleted': return 'Utilisateur supprimé';
      // Entities
      case 'entity_created': return 'Entité créée';
      case 'entity_updated': return 'Entité modifiée';
      case 'entity_deleted': return 'Entité supprimée';
      // Operations
      case 'operation_created': return 'Opération créée';
      case 'operation_updated': return 'Opération modifiée';
      case 'operation_deleted': return 'Opération supprimée';
      // Stripe
      case 'stripe_payment_created': return 'Paiement créé';
      case 'stripe_payment_success': return 'Paiement réussi';
      case 'stripe_payment_failed': return 'Paiement échoué';
      case 'stripe_payment_cancelled': return 'Paiement annulé';
      case 'stripe_terminal_error': return 'Erreur terminal';
      default: return eventType;
    }
  }

  /// Obtient la catégorie d'un type d'événement
  static String getCategory(String eventType) {
    if (eventType.startsWith('login') || eventType == 'logout') return 'auth';
    if (eventType.startsWith('passage')) return 'passages';
    if (eventType.startsWith('sector')) return 'sectors';
    if (eventType.startsWith('user')) return 'users';
    if (eventType.startsWith('entity')) return 'entities';
    if (eventType.startsWith('operation')) return 'operations';
    if (eventType.startsWith('stripe')) return 'stripe';
    return 'other';
  }
}

// Helpers pour parser les types depuis JSON (gère int/string)
int _parseInt(dynamic value) {
  if (value == null) return 0;
  if (value is int) return value;
  if (value is String) return int.tryParse(value) ?? 0;
  if (value is double) return value.toInt();
  return 0;
}

double _parseDouble(dynamic value) {
  if (value == null) return 0.0;
  if (value is double) return value;
  if (value is int) return value.toDouble();
  if (value is String) return double.tryParse(value) ?? 0.0;
  return 0.0;
}

List<String> _parseStringList(dynamic value) {
  if (value == null) return [];
  if (value is List) return value.map((e) => e.toString()).toList();
  return [];
}
