import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

enum EquipmentStatus {
  available,      // Disponible
  inUse,          // En prestation
  rented,         // Loué
  lost,           // Perdu
  outOfService,   // HS
  maintenance,    // En maintenance
}

String equipmentStatusToString(EquipmentStatus status) {
  switch (status) {
    case EquipmentStatus.available:
      return 'AVAILABLE';
    case EquipmentStatus.inUse:
      return 'IN_USE';
    case EquipmentStatus.rented:
      return 'RENTED';
    case EquipmentStatus.lost:
      return 'LOST';
    case EquipmentStatus.outOfService:
      return 'OUT_OF_SERVICE';
    case EquipmentStatus.maintenance:
      return 'MAINTENANCE';
  }
}

EquipmentStatus equipmentStatusFromString(String? status) {
  switch (status) {
    case 'AVAILABLE':
      return EquipmentStatus.available;
    case 'IN_USE':
      return EquipmentStatus.inUse;
    case 'RENTED':
      return EquipmentStatus.rented;
    case 'LOST':
      return EquipmentStatus.lost;
    case 'OUT_OF_SERVICE':
      return EquipmentStatus.outOfService;
    case 'MAINTENANCE':
      return EquipmentStatus.maintenance;
    default:
      return EquipmentStatus.available;
  }
}

enum EquipmentCategory {
  lighting,       // Lumière
  sound,          // Son
  video,          // Vidéo
  effect,        // Effets spéciaux
  structure,      // Structure
  consumable,     // Consommable
  cable,          // Câble
  vehicle,        // Véhicule
  backline,       // Régie / Backline
  other           // Autre
}

String equipmentCategoryToString(EquipmentCategory category) {
  switch (category) {
    case EquipmentCategory.lighting:
      return 'LIGHTING';
    case EquipmentCategory.sound:
      return 'SOUND';
    case EquipmentCategory.video:
      return 'VIDEO';
    case EquipmentCategory.structure:
      return 'STRUCTURE';
    case EquipmentCategory.consumable:
      return 'CONSUMABLE';
    case EquipmentCategory.cable:
      return 'CABLE';
    case EquipmentCategory.vehicle:
      return 'VEHICLE';
    case EquipmentCategory.backline:
      return 'BACKLINE';
    case EquipmentCategory.other:
      return 'OTHER';
    case EquipmentCategory.effect:
      return 'EFFECT';
  }
}

EquipmentCategory equipmentCategoryFromString(String? category) {
  switch (category) {
    case 'LIGHTING':
      return EquipmentCategory.lighting;
    case 'SOUND':
      return EquipmentCategory.sound;
    case 'VIDEO':
      return EquipmentCategory.video;
    case 'STRUCTURE':
      return EquipmentCategory.structure;
    case 'CONSUMABLE':
      return EquipmentCategory.consumable;
    case 'CABLE':
      return EquipmentCategory.cable;
    case 'VEHICLE':
      return EquipmentCategory.vehicle;
    case 'BACKLINE':
      return EquipmentCategory.backline;
    case 'EFFECT':
      return EquipmentCategory.effect;
    case 'OTHER':
    default:
      return EquipmentCategory.other;
  }
}

// Extensions pour centraliser les informations d'affichage
extension EquipmentCategoryExtension on EquipmentCategory {
  /// Retourne le label français de la catégorie
  String get label {
    switch (this) {
      case EquipmentCategory.lighting:
        return 'Lumière';
      case EquipmentCategory.sound:
        return 'Son';
      case EquipmentCategory.video:
        return 'Vidéo';
      case EquipmentCategory.effect:
        return 'Effets';
      case EquipmentCategory.structure:
        return 'Structure';
      case EquipmentCategory.consumable:
        return 'Consommable';
      case EquipmentCategory.cable:
        return 'Câble';
      case EquipmentCategory.vehicle:
        return 'Véhicule';
      case EquipmentCategory.backline:
        return 'Régie / Backline';
      case EquipmentCategory.other:
        return 'Autre';
    }
  }

  /// Retourne l'icône Material de la catégorie
  IconData get iconData {
    switch (this) {
      case EquipmentCategory.lighting:
        return Icons.light_mode;
      case EquipmentCategory.sound:
        return Icons.volume_up;
      case EquipmentCategory.video:
        return Icons.videocam;
      case EquipmentCategory.effect:
        return Icons.auto_awesome;
      case EquipmentCategory.structure:
        return Icons.construction;
      case EquipmentCategory.consumable:
        return Icons.inventory_2;
      case EquipmentCategory.cable:
        return Icons.cable;
      case EquipmentCategory.vehicle:
        return Icons.local_shipping;
      case EquipmentCategory.backline:
        return Icons.piano;
      case EquipmentCategory.other:
        return Icons.more_horiz;
    }
  }

  /// Retourne la couleur associée à la catégorie
  Color get color {
    switch (this) {
      case EquipmentCategory.lighting:
        return Colors.yellow.shade700;
      case EquipmentCategory.sound:
        return Colors.purple;
      case EquipmentCategory.video:
        return Colors.blue;
      case EquipmentCategory.effect:
        return Colors.pink;
      case EquipmentCategory.structure:
        return Colors.brown;
      case EquipmentCategory.consumable:
        return Colors.orange;
      case EquipmentCategory.cable:
        return Colors.grey;
      case EquipmentCategory.vehicle:
        return Colors.teal;
      case EquipmentCategory.backline:
        return Colors.indigo;
      case EquipmentCategory.other:
        return Colors.blueGrey;
    }
  }

  /// Retourne le chemin de l'icône personnalisée (si disponible)
  String? get customIconPath {
    switch (this) {
      case EquipmentCategory.structure:
        return 'assets/icons/truss.svg';
      case EquipmentCategory.consumable:
        return 'assets/icons/tape.svg';
      case EquipmentCategory.lighting:
      case EquipmentCategory.sound:
      case EquipmentCategory.video:
      case EquipmentCategory.effect:
      case EquipmentCategory.cable:
      case EquipmentCategory.vehicle:
      case EquipmentCategory.backline:
      case EquipmentCategory.other:
        return null;
    }
  }

  /// Vérifie si une icône personnalisée est disponible
  bool get hasCustomIcon => customIconPath != null;

  /// Retourne l'icône Widget à afficher (unifié pour Material et personnalisé)
  Widget getIcon({double size = 24, Color? color}) {
    final customPath = customIconPath;
    if (customPath != null) {
      // Détection automatique du format (SVG ou PNG)
      final isSvg = customPath.toLowerCase().endsWith('.svg');

      if (isSvg) {
        // SVG : on peut appliquer la couleur sans dégrader la qualité
        return SvgPicture.asset(
          customPath,
          width: size,
          height: size,
          colorFilter: color != null
            ? ColorFilter.mode(color, BlendMode.srcIn)
            : null,
          placeholderBuilder: (context) => Icon(iconData, size: size, color: color),
        );
      } else {
        // PNG : on n'applique PAS le color filter pour préserver la qualité
        return Image.asset(
          customPath,
          width: size,
          height: size,
          filterQuality: FilterQuality.high,
          errorBuilder: (context, error, stackTrace) {
            return Icon(iconData, size: size, color: color);
          },
        );
      }
    }
    return Icon(iconData, size: size, color: color);
  }

  /// Version pour CircleAvatar et contextes similaires (sans ColorFilter si Material Icon)
  Widget getIconForAvatar({double size = 24, Color? color}) {
    final customPath = customIconPath;
    if (customPath != null) {
      final isSvg = customPath.toLowerCase().endsWith('.svg');

      if (isSvg) {
        return SvgPicture.asset(
          customPath,
          width: size,
          height: size,
          colorFilter: color != null
            ? ColorFilter.mode(color, BlendMode.srcIn)
            : null,
          placeholderBuilder: (context) => Icon(iconData, size: size, color: color),
        );
      } else {
        return Image.asset(
          customPath,
          width: size,
          height: size,
          filterQuality: FilterQuality.high,
          errorBuilder: (context, error, stackTrace) {
            return Icon(iconData, size: size, color: color);
          },
        );
      }
    }
    return Icon(iconData, size: size, color: color);
  }
}


extension EquipmentStatusExtension on EquipmentStatus {
  /// Retourne le label français du statut
  String get label {
    switch (this) {
      case EquipmentStatus.available:
        return 'Disponible';
      case EquipmentStatus.inUse:
        return 'En prestation';
      case EquipmentStatus.rented:
        return 'Loué';
      case EquipmentStatus.lost:
        return 'Perdu';
      case EquipmentStatus.outOfService:
        return 'HS';
      case EquipmentStatus.maintenance:
        return 'Maintenance';
    }
  }

  /// Retourne la couleur associée au statut
  Color get color {
    switch (this) {
      case EquipmentStatus.available:
        return Colors.green;
      case EquipmentStatus.inUse:
        return Colors.blue;
      case EquipmentStatus.rented:
        return Colors.orange;
      case EquipmentStatus.lost:
        return Colors.red;
      case EquipmentStatus.outOfService:
        return Colors.red.shade900;
      case EquipmentStatus.maintenance:
        return Colors.amber;
    }
  }
}

class EquipmentModel {
  final String id;                          // Identifiant unique (clé)
  final String name;                        // Nom de l'équipement
  final String? brand;                      // Marque (indexé)
  final String? model;                      // Modèle (indexé)
  final EquipmentCategory category;         // Catégorie
  final String? subCategory;                // Sous-catégorie (indexé par catégorie)
  final EquipmentStatus status;             // Statut actuel

  // Prix (visible uniquement avec manage_equipment)
  final double? purchasePrice;              // Prix d'achat
  final double? rentalPrice;                // Prix de location

  // Quantité (pour consommables/câbles)
  final int? totalQuantity;                 // Quantité totale
  final int? availableQuantity;             // Quantité disponible
  final int? criticalThreshold;             // Seuil critique pour alerte


  // Caractéristiques physiques
  final double? weight;                     // Poids (kg)
  final double? length;                     // Longueur (cm)
  final double? width;                      // Largeur (cm)
  final double? height;                     // Hauteur (cm)

  // Dates & maintenance
  final DateTime? purchaseDate;             // Date d'achat
  final DateTime? lastMaintenanceDate;      // Dernière maintenance
  final DateTime? nextMaintenanceDate;      // Prochaine maintenance prévue

  // Maintenances (références)
  final List<String> maintenanceIds;        // IDs des opérations de maintenance

  // Image
  final String? imageUrl;                   // URL de l'image (Storage /materiel)

  // Métadonnées
  final String? notes;                      // Notes additionnelles
  final DateTime createdAt;                 // Date de création
  final DateTime updatedAt;                 // Date de mise à jour

  EquipmentModel({
    required this.id,
    required this.name,
    this.brand,
    this.model,
    required this.category,
    this.subCategory,
    this.status = EquipmentStatus.available,
    this.purchasePrice,
    this.rentalPrice,
    this.totalQuantity,
    this.availableQuantity,
    this.criticalThreshold,
    this.weight,
    this.length,
    this.width,
    this.height,
    this.purchaseDate,
    this.lastMaintenanceDate,
    this.nextMaintenanceDate,
    this.maintenanceIds = const [],
    this.imageUrl,
    this.notes,
    required this.createdAt,
    required this.updatedAt,
  });

  factory EquipmentModel.fromMap(Map<String, dynamic> map, String id) {
    // Fonction helper pour convertir de manière sécurisée en double
    double? parseDouble(dynamic value) {
      if (value == null) return null;
      if (value is num) return value.toDouble();
      if (value is String) return double.tryParse(value);
      return null;
    }

    // Fonction helper pour convertir de manière sécurisée en int
    int? parseInt(dynamic value) {
      if (value == null) return null;
      if (value is num) return value.toInt();
      if (value is String) return int.tryParse(value);
      return null;
    }

    // Fonction helper pour convertir Timestamp ou String ISO ou int epoch en DateTime
    DateTime? parseDate(dynamic value) {
      if (value == null) return null;
      if (value is Timestamp) return value.toDate();
      if (value is String) return DateTime.tryParse(value);
      if (value is int) return DateTime.fromMillisecondsSinceEpoch(value);
      return null;
    }

    // Gestion sécurisée des listes d'IDs de maintenance
    final List<String> maintenanceIds = [];
    if (map['maintenanceIds'] is List) {
      for (final e in map['maintenanceIds'] as List) {
        if (e != null) {
          maintenanceIds.add(e.toString());
        }
      }
    }

    return EquipmentModel(
      id: id,
      name: (map['name'] ?? '').toString(),
      brand: map['brand']?.toString(),
      model: map['model']?.toString(),
      category: equipmentCategoryFromString(map['category']?.toString()),
      subCategory: map['subCategory']?.toString(),
      status: equipmentStatusFromString(map['status']?.toString()),
      purchasePrice: parseDouble(map['purchasePrice']),
      rentalPrice: parseDouble(map['rentalPrice']),
      totalQuantity: parseInt(map['totalQuantity']),
      availableQuantity: parseInt(map['availableQuantity']),
      criticalThreshold: parseInt(map['criticalThreshold']),
      weight: parseDouble(map['weight']),
      length: parseDouble(map['length']),
      width: parseDouble(map['width']),
      height: parseDouble(map['height']),
      purchaseDate: parseDate(map['purchaseDate']),
      lastMaintenanceDate: parseDate(map['lastMaintenanceDate']),
      nextMaintenanceDate: parseDate(map['nextMaintenanceDate']),
      maintenanceIds: maintenanceIds,
      imageUrl: map['imageUrl']?.toString(),
      notes: map['notes']?.toString(),
      createdAt: parseDate(map['createdAt']) ?? DateTime.now(),
      updatedAt: parseDate(map['updatedAt']) ?? DateTime.now(),
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'name': name,
      'brand': brand,
      'model': model,
      'category': equipmentCategoryToString(category),
      'subCategory': subCategory,
      'status': equipmentStatusToString(status),
      'purchasePrice': purchasePrice,
      'rentalPrice': rentalPrice,
      'totalQuantity': totalQuantity,
      'availableQuantity': availableQuantity,
      'criticalThreshold': criticalThreshold,
      'weight': weight,
      'length': length,
      'width': width,
      'height': height,
      'lastMaintenanceDate': lastMaintenanceDate != null ? Timestamp.fromDate(lastMaintenanceDate!) : null,
      'purchaseDate': purchaseDate != null ? Timestamp.fromDate(purchaseDate!) : null,
      'nextMaintenanceDate': nextMaintenanceDate != null ? Timestamp.fromDate(nextMaintenanceDate!) : null,
      'maintenanceIds': maintenanceIds,
      'imageUrl': imageUrl,
      'notes': notes,
      'createdAt': Timestamp.fromDate(createdAt),
      'updatedAt': Timestamp.fromDate(updatedAt),
    };
  }

  EquipmentModel copyWith({
    String? id,
    String? brand,
    String? name,
    String? model,
    EquipmentCategory? category,
    String? subCategory,
    EquipmentStatus? status,
    double? purchasePrice,
    double? rentalPrice,
    int? totalQuantity,
    int? availableQuantity,
    int? criticalThreshold,
    double? weight,
    double? length,
    double? width,
    double? height,
    DateTime? purchaseDate,
    DateTime? lastMaintenanceDate,
    DateTime? nextMaintenanceDate,
    List<String>? maintenanceIds,
    String? imageUrl,
    String? notes,
    DateTime? createdAt,
    DateTime? updatedAt,
  }) {
    return EquipmentModel(
      id: id ?? this.id,
      brand: brand ?? this.brand,
      name: name ?? this.name,
      model: model ?? this.model,
      category: category ?? this.category,
      subCategory: subCategory ?? this.subCategory,
      status: status ?? this.status,
      purchasePrice: purchasePrice ?? this.purchasePrice,
      rentalPrice: rentalPrice ?? this.rentalPrice,
      totalQuantity: totalQuantity ?? this.totalQuantity,
      availableQuantity: availableQuantity ?? this.availableQuantity,
      criticalThreshold: criticalThreshold ?? this.criticalThreshold,
      weight: weight ?? this.weight,
      length: length ?? this.length,
      width: width ?? this.width,
      height: height ?? this.height,
      lastMaintenanceDate: lastMaintenanceDate ?? this.lastMaintenanceDate,
      purchaseDate: purchaseDate ?? this.purchaseDate,
      nextMaintenanceDate: nextMaintenanceDate ?? this.nextMaintenanceDate,
      maintenanceIds: maintenanceIds ?? this.maintenanceIds,
      imageUrl: imageUrl ?? this.imageUrl,
      notes: notes ?? this.notes,
      createdAt: createdAt ?? this.createdAt,
      updatedAt: updatedAt ?? this.updatedAt,
    );
  }

  // Helper pour vérifier si c'est un consommable/câble avec quantité
  bool get hasQuantity => category == EquipmentCategory.consumable || category == EquipmentCategory.cable;

  // Helper pour vérifier si le stock est critique
  bool get isCriticalStock {
    if (!hasQuantity || criticalThreshold == null || availableQuantity == null) {
      return false;
    }
    return availableQuantity! <= criticalThreshold!;
  }

  // Helper pour vérifier si la maintenance est à venir
  bool get isMaintenanceDue {
    if (nextMaintenanceDate == null) return false;
    return nextMaintenanceDate!.isBefore(DateTime.now().add(const Duration(days: 7)));
  }
}

