import 'package:equatable/equatable.dart';
import 'package:flux/core/enums_and_consts/consts.dart';
import 'package:flux/core/utils/extensions.dart';
import 'package:flux/features/attachments/models/attachment_model.dart';
import 'package:flux/features/customers/models/customer_model.dart';
import 'package:flux/features/master_data/providers/models/provider_model.dart';

enum OperationStatus {
  success('success', 'OK'),
  waitingForAction('waiting_for_action', 'In attesa di azione'),
  waitingForSupport('waiting_for_support', 'In attesa di supporto'),
  failure('failure', 'KO'),
  draft('draft', 'Bozza');

  static OperationStatus fromString(String value) {
    final normalizedValue = value.replaceAll('_', '').toLowerCase();
    return OperationStatus.values.firstWhere(
      (e) => e.name.toLowerCase() == normalizedValue,
    );
  }

  final String supabaseName;
  final String displayName;

  const OperationStatus(this.supabaseName, this.displayName);
}

class OperationModel extends Equatable {
  final String? id;
  final DateTime? createdAt;
  final String type;
  final String? subType;
  final String? providerId;
  final String? modelId;
  final String? modelDisplayName;
  final String? description;
  final DateTime? expirationDate;
  final String note;
  final bool showInDashboard;
  final String batchUuid;
  final String companyId;
  final String storeId;
  final String? storeDisplayName;
  final int quantity;
  final String? staffId;
  final String? staffDisplayName;
  final String? lastCampaignId;
  final OperationStatus status;
  final String? customerId;
  final CustomerModel? customer;
  final String reference;
  final bool isBusiness;
  final ProviderModel? provider;

  // ALLEGATI (Aggiunto)
  final List<AttachmentModel> attachments;

  const OperationModel({
    this.id,
    this.createdAt,
    this.type = '',
    this.subType,
    this.providerId,
    this.modelId,
    this.modelDisplayName,
    this.description,
    this.expirationDate,
    this.note = '',
    this.showInDashboard = true,
    this.batchUuid = '',
    required this.companyId,
    this.storeId = '',
    this.storeDisplayName,
    this.quantity = 1,
    this.staffId,
    this.staffDisplayName,
    this.lastCampaignId,
    this.status = OperationStatus.draft,
    this.customerId,
    this.customer,
    this.reference = '',
    this.attachments = const [],
    this.isBusiness = false,
    this.provider,
  });

  OperationModel copyWith({
    String? id,
    DateTime? createdAt,
    String? type,
    String? subType,
    // 🥷 TRUCCO APPLICATO ANCHE QUI:
    String? Function()? providerId,
    ProviderModel? Function()? provider,
    String? modelId,
    String? modelDisplayName,
    String? description,
    DateTime? expirationDate,
    String? note,
    bool? showInDashboard,
    String? batchUuid,
    String? companyId,
    String? storeId,
    String? storeDisplayName,
    int? quantity,
    String? staffId,
    String? staffDisplayName,
    String? lastCampaignId,
    OperationStatus? status,
    String? customerId,
    CustomerModel? customer,
    String? reference,
    List<AttachmentModel>? attachments,
    bool? isBusiness,
  }) => OperationModel(
    id: id ?? this.id,
    createdAt: createdAt ?? this.createdAt,
    type: type ?? this.type,
    subType: subType ?? this.subType,
    // Se la funzione è passata, la eseguiamo (anche se ritorna null), altrimenti teniamo il vecchio
    providerId: providerId != null ? providerId() : this.providerId,
    provider: provider != null ? provider() : this.provider,

    modelId: modelId ?? this.modelId,
    modelDisplayName: modelDisplayName ?? this.modelDisplayName,
    description: description ?? this.description,
    expirationDate: expirationDate ?? this.expirationDate,
    note: note ?? this.note,
    showInDashboard: showInDashboard ?? this.showInDashboard,
    batchUuid: batchUuid ?? this.batchUuid,
    companyId: companyId ?? this.companyId,
    storeId: storeId ?? this.storeId,
    storeDisplayName: storeDisplayName ?? this.storeDisplayName,
    quantity: quantity ?? this.quantity,
    staffId: staffId ?? this.staffId,
    staffDisplayName: staffDisplayName ?? this.staffDisplayName,
    lastCampaignId: lastCampaignId ?? this.lastCampaignId,
    status: status ?? this.status,
    customerId: customerId ?? this.customerId,
    customer: customer ?? this.customer,
    reference: reference ?? this.reference,
    attachments: attachments ?? this.attachments,
    isBusiness: isBusiness ?? this.isBusiness,
  );

  @override
  List<Object?> get props => [
    id,
    createdAt,
    type,
    subType,
    providerId,
    provider,
    modelId,
    modelDisplayName,
    description,
    expirationDate,
    note,
    showInDashboard,
    batchUuid,
    companyId,
    storeId,
    storeDisplayName,
    quantity,
    staffId,
    staffDisplayName,
    lastCampaignId,
    status,
    customerId,
    customer,
    reference,
    attachments,
    isBusiness,
  ];

  factory OperationModel.empty() {
    return OperationModel(id: null, createdAt: null, companyId: '');
  }

  factory OperationModel.fromMap(Map<String, dynamic> map) {
    return OperationModel(
      id: map['id'] as String?,
      createdAt: map['created_at'] != null
          ? DateTime.parse(map['created_at'])
          : null,
      type: map['type'] as String? ?? '',
      subType: map['sub_type'] as String?,

      // I campi relazionali nullabili restano rigorosamente null!
      providerId: map['provider_id'] as String?,
      // MAGIA ANTI-CRASH: Usiamo ?['chiave'] per non far esplodere i join vuoti
      provider: (map[Tables.providers] != null)
          ? ProviderModel.fromMap(map[Tables.providers] as Map<String, dynamic>)
          : null,

      modelId: map['model_id'] as String?,
      modelDisplayName: (map[Tables.models]?['name_with_brand'] as String?)
          ?.myFormat(),

      description: map['description'] as String?,
      expirationDate: map['expiration_date'] != null
          ? DateTime.parse(map['expiration_date'])
          : null,
      note: map['note'] as String? ?? '',
      showInDashboard: map['show_in_dashboard'] as bool? ?? true,
      batchUuid: map['batch_uuid'] as String? ?? '',
      companyId: map['company_id'] as String,

      storeId:
          map['store_id'] as String? ??
          '', // Questo è non-nullable nella tua classe
      storeDisplayName: (map[Tables.stores]?['name'] as String?)?.myFormat(),

      quantity: map['quantity'] is int
          ? map['quantity']
          : int.tryParse(map['quantity']?.toString() ?? '1') ?? 1,

      staffId: map['staff_id'] as String?,
      staffDisplayName: (map[Tables.staffMembers]?['name'] as String?)
          ?.myFormat(),

      lastCampaignId: map['last_campaign_id'] as String?,
      status: OperationStatus.fromString(map['status'] ?? 'draft'),
      customerId: map['customer_id'] as String?,

      customer: map[Tables.customers] != null
          ? CustomerModel.fromMap(map[Tables.customers] as Map<String, dynamic>)
          : null,

      attachments:
          (map[Tables.attachments] as List?)
              ?.map((x) => AttachmentModel.fromMap(x))
              .toList() ??
          const [],

      reference: map['reference'] as String? ?? '',
      isBusiness: map['is_business'] as bool? ?? false,
    );
  }

  Map<String, dynamic> toMap() {
    return {
      if (id != null) 'id': id,
      'type': type,
      'sub_type': subType,
      'provider_id': providerId,
      'model_id': modelId,
      'description': description,
      if (expirationDate != null)
        'expiration_date': expirationDate!.toIso8601String(),
      'note': note,
      'show_in_dashboard': showInDashboard,
      'batch_uuid': batchUuid,
      'company_id': companyId,
      'store_id': storeId,
      'quantity': quantity,
      if (staffId != null) 'staff_id': staffId,
      if (lastCampaignId != null) 'last_campaign_id': lastCampaignId,
      'status': status.supabaseName,
      if (customerId != null) 'customer_id': customerId,
      'reference': reference,
      'is_business': isBusiness,
    };
  }
}
