import 'package:equatable/equatable.dart';

// ===================================================================
// ENUMS (Paranoia Mode per la lettura dal DB)
// ===================================================================

enum SubscriptionTier {
  free,
  pro,
  premium,
  platinum;

  static SubscriptionTier fromString(String? value) {
    return SubscriptionTier.values.firstWhere(
      (e) => e.name == value,
      orElse: () => SubscriptionTier.free, // Fallback di sicurezza
    );
  }
}

enum SubscriptionStatus {
  trialing,
  active,
  pastDue,
  canceled;

  static SubscriptionStatus fromString(String? value) {
    if (value == null) return SubscriptionStatus.canceled;
    // Normalizziamo 'past_due' dal DB in 'pastdue' per il match con l'Enum
    final normalizedValue = value.replaceAll('_', '').toLowerCase();
    return SubscriptionStatus.values.firstWhere(
      (e) => e.name.toLowerCase() == normalizedValue,
      orElse: () => SubscriptionStatus.canceled,
    );
  }
}

enum LabelFormat {
  none,
  small_62x29,
  medium_54x101,
  large_102x152,
  custom;

  static LabelFormat fromString(String? value) {
    return LabelFormat.values.firstWhere(
      (e) => e.name == value,
      orElse: () => LabelFormat.none,
    );
  }
}

// ===================================================================
// IL MODELLO ESATTO
// ===================================================================

class CompanyModel extends Equatable {
  final String? id;
  final DateTime? createdAt;
  final String userId; // Nel DB è user_id (chiave esterna su auth.users)

  // Dati Anagrafici e Fatturazione
  final String name;
  final String address;
  final String zipCode;
  final String city;
  final String province;
  final String vatId;
  final String fiscalCode;
  final String sdi;
  final String? phone;
  final String? email;
  final String? logoUrl;
  final String? ticketDisclaimer;
  final LabelFormat labelFormat;
  final double? labelWidth;
  final double? labelHeight;
  final bool isLabelVertical;
  // Stato Pagamenti (Ibride: manuale + Stripe)
  final bool isPaid;
  final DateTime? paymentExpiration;

  // Campi SaaS Stripe/Automazioni
  final SubscriptionTier subscriptionTier;
  final SubscriptionStatus subscriptionStatus;
  final DateTime? trialEndsAt;
  final String? stripeCustomerId;
  final String? stripeSubscriptionId;

  const CompanyModel({
    this.id,
    this.createdAt,
    required this.userId,
    required this.name,
    required this.address,
    required this.zipCode,
    required this.city,
    required this.province,
    required this.vatId,
    required this.fiscalCode,
    required this.sdi,
    this.phone,
    this.email,
    this.logoUrl,
    this.ticketDisclaimer,
    this.labelFormat = LabelFormat.none,
    this.labelWidth,
    this.labelHeight,
    this.isLabelVertical = false,
    this.isPaid = false,
    this.paymentExpiration,
    this.subscriptionTier = SubscriptionTier.free,
    this.subscriptionStatus = SubscriptionStatus.trialing,
    this.trialEndsAt,
    this.stripeCustomerId,
    this.stripeSubscriptionId,
  });

  CompanyModel copyWith({
    String? id,
    DateTime? createdAt,
    String? userId,
    String? name,
    String? address,
    String? zipCode,
    String? city,
    String? province,
    String? vatId,
    String? fiscalCode,
    String? sdi,
    String? logoUrl,
    String? ticketDisclaimer,
    LabelFormat? labelFormat,
    double? labelWidth,
    double? labelHeight,
    bool? isLabelVertical,
    String? phone,
    String? email,
    bool? isPaid,
    DateTime? paymentExpiration,
    SubscriptionTier? subscriptionTier,
    SubscriptionStatus? subscriptionStatus,
    DateTime? trialEndsAt,
    String? stripeCustomerId,
    String? stripeSubscriptionId,
  }) {
    return CompanyModel(
      id: id ?? this.id,
      createdAt: createdAt ?? this.createdAt,
      userId: userId ?? this.userId,
      name: name ?? this.name,
      address: address ?? this.address,
      zipCode: zipCode ?? this.zipCode,
      city: city ?? this.city,
      province: province ?? this.province,
      vatId: vatId ?? this.vatId,
      fiscalCode: fiscalCode ?? this.fiscalCode,
      sdi: sdi ?? this.sdi,
      logoUrl: logoUrl ?? this.logoUrl,
      phone: phone ?? this.phone,
      email: email ?? this.email,
      ticketDisclaimer: ticketDisclaimer ?? this.ticketDisclaimer,
      labelFormat: labelFormat ?? this.labelFormat,
      labelWidth: labelWidth ?? this.labelWidth,
      labelHeight: labelHeight ?? this.labelHeight,
      isLabelVertical: isLabelVertical ?? this.isLabelVertical,
      isPaid: isPaid ?? this.isPaid,
      paymentExpiration: paymentExpiration ?? this.paymentExpiration,
      subscriptionTier: subscriptionTier ?? this.subscriptionTier,
      subscriptionStatus: subscriptionStatus ?? this.subscriptionStatus,
      trialEndsAt: trialEndsAt ?? this.trialEndsAt,
      stripeCustomerId: stripeCustomerId ?? this.stripeCustomerId,
      stripeSubscriptionId: stripeSubscriptionId ?? this.stripeSubscriptionId,
    );
  }

  factory CompanyModel.empty() {
    return const CompanyModel(
      id: null,
      createdAt: null,
      userId: '',
      name: '',
      address: '',
      zipCode: '',
      city: '',
      province: '',
      vatId: '',
      fiscalCode: '',
      sdi: '',
    );
  }

  factory CompanyModel.fromMap(Map<String, dynamic> map) {
    return CompanyModel(
      id: map['id'] as String?,
      createdAt: map['created_at'] != null
          ? DateTime.tryParse(map['created_at'])
          : null,
      userId: map['user_id'] ?? '',
      name: map['name'] ?? '',
      address: map['address'] ?? '',
      zipCode: map['zip_code'] ?? '',
      city: map['city'] ?? '',
      province: map['province'] ?? '',
      vatId: map['vat_id'] ?? '',
      fiscalCode: map['fiscal_code'] ?? '',
      sdi: map['sdi'] ?? '',
      logoUrl: map['logo_url'],
      phone: map['phone'] ?? '',
      email: map['email'] ?? '',
      ticketDisclaimer: map['ticket_disclaimer'],
      labelFormat: LabelFormat.fromString(map['label_format']),
      labelWidth: map['label_width'] != null
          ? (map['label_width'] as num).toDouble()
          : null,
      labelHeight: map['label_height'] != null
          ? (map['label_height'] as num).toDouble()
          : null,
      isLabelVertical: map['is_label_vertical'] ?? false,
      isPaid: map['is_paid'] ?? false,
      paymentExpiration: map['payment_expiration'] != null
          ? DateTime.tryParse(map['payment_expiration'])
          : null,
      subscriptionTier: SubscriptionTier.fromString(map['subscription_tier']),
      subscriptionStatus: SubscriptionStatus.fromString(
        map['subscription_status'],
      ),
      trialEndsAt: map['trial_ends_at'] != null
          ? DateTime.tryParse(map['trial_ends_at'])
          : null,
      stripeCustomerId: map['stripe_customer_id'],
      stripeSubscriptionId: map['stripe_subscription_id'],
    );
  }

  Map<String, dynamic> toMap() {
    return {
      if (id != null) 'id': id,
      // created_at è gestito dal DB di default, di solito non si passa nell'insert
      'user_id': userId,
      'name': name,
      'address': address,
      'zip_code': zipCode,
      'city': city,
      'province': province,
      'vat_id': vatId,
      'fiscal_code': fiscalCode,
      'sdi': sdi,
      'logo_url': logoUrl,
      'phone': phone,
      'email': email,
      'ticket_disclaimer': ticketDisclaimer,
      'label_format': labelFormat.name,
      'label_width': labelWidth,
      'label_height': labelHeight,
      'is_label_vertical': isLabelVertical,
      'is_paid': isPaid,
      if (paymentExpiration != null)
        'payment_expiration': paymentExpiration!.toIso8601String(),
      'subscription_tier': subscriptionTier.name,
      'subscription_status': subscriptionStatus == SubscriptionStatus.pastDue
          ? 'past_due'
          : subscriptionStatus.name,
      if (trialEndsAt != null) 'trial_ends_at': trialEndsAt!.toIso8601String(),
      if (stripeCustomerId != null) 'stripe_customer_id': stripeCustomerId,
      if (stripeSubscriptionId != null)
        'stripe_subscription_id': stripeSubscriptionId,
    };
  }

  @override
  List<Object?> get props => [
    id,
    createdAt,
    userId,
    name,
    address,
    zipCode,
    city,
    province,
    vatId,
    fiscalCode,
    sdi,
    logoUrl,
    phone,
    email,
    ticketDisclaimer,
    labelFormat,
    labelWidth,
    labelHeight,
    isLabelVertical,
    isPaid,
    paymentExpiration,
    subscriptionTier,
    subscriptionStatus,
    trialEndsAt,
    stripeCustomerId,
    stripeSubscriptionId,
  ];
}

// ===================================================================
// BUSINESS LOGIC: I LIMITI DEI TIER
// ===================================================================

extension CompanyLimits on CompanyModel {
  int get maxStores {
    switch (subscriptionTier) {
      case SubscriptionTier.free:
        return 1;
      case SubscriptionTier.pro:
        return 1;
      case SubscriptionTier.premium:
        return 10;
      case SubscriptionTier.platinum:
        return 30;
    }
  }

  int get maxStaffMembers {
    switch (subscriptionTier) {
      case SubscriptionTier.free:
        return 2;
      case SubscriptionTier.pro:
        return 10;
      case SubscriptionTier.premium:
        return 50;
      case SubscriptionTier.platinum:
        return 150;
    }
  }

  int get maxOperationsPerMonth {
    switch (subscriptionTier) {
      case SubscriptionTier.free:
        return 50;
      case SubscriptionTier.pro:
        return 1000;
      case SubscriptionTier.premium:
        return 10000;
      case SubscriptionTier.platinum:
        return 30000;
    }
  }

  int get maxStorageGb {
    switch (subscriptionTier) {
      case SubscriptionTier.free:
        return 0; // 500MB = 0.5 GB, magari qui usi i MB interi
      case SubscriptionTier.pro:
        return 3;
      case SubscriptionTier.premium:
        return 30;
      case SubscriptionTier.platinum:
        return 100;
    }
  }

  /// Verifica generale: L'utente ha i permessi per usare l'app?
  bool get hasActiveAccess {
    // 1. Priorità all'override manuale (is_paid e payment_expiration)
    if (isPaid) {
      if (paymentExpiration == null) {
        return true; // Pagato "a vita" o senza scadenza
      }
      if (DateTime.now().isBefore(paymentExpiration!)) return true;
    }

    // 2. Controllo SaaS (Stripe/Subscription)
    if (subscriptionStatus == SubscriptionStatus.active) return true;

    // 3. Controllo Trial
    if (subscriptionStatus == SubscriptionStatus.trialing &&
        trialEndsAt != null) {
      return DateTime.now().isBefore(trialEndsAt!);
    }

    // Scaduto, past_due, o cancellato
    return false;
  }
}
