import 'package:equatable/equatable.dart';
import 'package:flux/core/utils/extensions.dart';
import 'package:flux/features/customers/models/customer_model.dart';
import 'package:flux/features/tickets/models/shipping_document_model.dart';

/// Enum per il tipo di ticket
enum TicketType {
  repair('repair', 'Riparazione'),
  softwareSetup('software_setup', 'Impost. software'),
  dataTransfer('data_transfer', 'Trasf. dati'),
  operationTicket('operation_ticket', 'Ticket operazione'),
  other('other', 'Altro');

  final String value;
  final String displayValue;
  const TicketType(this.value, this.displayValue);

  static TicketType fromString(String val) {
    return TicketType.values.firstWhere(
      (e) => e.value == val,
      orElse: () => TicketType.other,
    );
  }
}

/// Enum per lo stato del ticket
enum TicketStatus {
  open('open', 'Aperto'),
  inProgress('in_progress', 'In corso'),
  waitingForParts('waiting_for_parts', 'In attesa di ricambi'),
  ready('ready', 'Pronto'),
  closed('closed', 'Chiuso'),
  waitingForShipping('waiting_for_shipping', 'In attesa di spedire'),
  waitingForReturn('waiting_for_return', 'In attesa di ritorno'),
  waitingForQuote('waiting_for_quote', 'In attesa di preventivo'),
  waitingForCustomer('waiting_for_customer', 'In attesa del cliente');

  final String value;
  final String displayValue;
  const TicketStatus(this.value, this.displayValue);

  static TicketStatus fromString(String? val) {
    return TicketStatus.values.firstWhere(
      (e) => e.value == val,
      orElse: () => TicketStatus.open,
    );
  }
}

/// Enum per il risultato del ticket (OK / KO)
enum TicketResult {
  success('success', 'Risolto (OK)'),
  failure('failure', 'Non Risolto (KO)');

  final String value;
  final String displayValue;
  const TicketResult(this.value, this.displayValue);

  static TicketResult? fromString(String? val) {
    if (val == null) return null;
    return TicketResult.values.firstWhere(
      (e) => e.value == val,
      orElse: () => TicketResult.success,
    );
  }
}

/// Enum per il tipo di garanzia
enum WarrantyType {
  manufacturerWarranty('manufacturer_warranty', 'Garanzia produttore'),
  providerWarranty('provider_warranty', 'Garanzia gestore'),
  internalWarranty('internal_warranty', 'Garanzia interna'),
  noWarranty('no_warranty', 'Fuori garanzia');

  final String value;
  final String displayValue;
  const WarrantyType(this.value, this.displayValue);

  static WarrantyType? fromString(String? val) {
    return WarrantyType.values.firstWhere(
      (e) => e.value == val,
      orElse: () => WarrantyType.noWarranty,
    );
  }
}

class TicketModel extends Equatable {
  final String? id; // Null se non ancora salvato
  final DateTime? createdAt;
  final String companyId;
  final String? storeId;
  final String? customerId;
  final String? targetModelId;
  final String? targetSn;
  final String? targetPassword;
  final String? sourceModelId;
  final String? sourceSn;
  final String? sourcePassword;
  final double customerPrice;
  final double internalCost;
  final DateTime? closedAt;
  final DateTime? returnedAt;
  final String request;
  final WarrantyType? warrantyType;
  final String? publicNotes;
  final String? internalNotes;
  final String? referenceId;
  final String? alternativePhoneNumber;
  final bool hasCourtesyDevice;
  final TicketType ticketType;
  final TicketStatus ticketStatus;
  final DateTime? estimatedDeliveryAt;
  final TicketResult? ticketResult;
  final String? resolutionNotes;
  final String? shippingDocumentId;
  final CustomerModel? customer;
  final String? targetModelName;
  final String? sourceModelName;
  final String? createdById;
  final String? createdByName;
  final String? assignedToId;
  final String? assignedToName;
  final String? includedAccessories;
  final ShippingDocumentModel? shippingDocument;

  const TicketModel({
    this.id,
    this.createdAt,
    required this.companyId,
    this.storeId,
    this.customerId,
    this.targetModelId,
    this.targetSn,
    this.targetPassword,
    this.sourceModelId,
    this.sourceSn,
    this.sourcePassword,
    this.customerPrice = 0.0,
    this.internalCost = 0.0,
    this.closedAt,
    this.returnedAt,
    this.request = '',
    this.warrantyType,
    this.publicNotes,
    this.internalNotes,
    this.referenceId,
    this.alternativePhoneNumber,
    this.hasCourtesyDevice = false,
    required this.ticketType,
    this.ticketStatus = TicketStatus.closed,
    this.estimatedDeliveryAt,
    this.ticketResult,
    this.resolutionNotes,
    this.shippingDocumentId,
    this.customer,
    this.targetModelName,
    this.sourceModelName,
    this.createdById,
    this.createdByName,
    this.assignedToId,
    this.assignedToName,
    this.includedAccessories,
    this.shippingDocument,
  });

  /// Factory per creare un ticket vuoto (utile per i form di creazione)
  factory TicketModel.empty({String? companyId, String? storeId}) {
    return TicketModel(
      companyId: companyId ?? '',
      storeId: storeId,
      ticketType: TicketType.repair, // Valore di default
      ticketStatus: TicketStatus.open,
      customerPrice: 0.0,
      internalCost: 0.0,
      hasCourtesyDevice: false,
      request: '',
    );
  }

  TicketModel copyWith({
    String? id,
    DateTime? createdAt,
    String? companyId,
    String? storeId,
    String? customerId,
    String? targetModelId,
    String? targetSn,
    String? targetPassword,
    String? sourceModelId,
    String? sourceSn,
    String? sourcePassword,
    double? customerPrice,
    double? internalCost,
    DateTime? closedAt,
    DateTime? returnedAt,
    String? request,
    WarrantyType? warrantyType,
    String? publicNotes,
    String? internalNotes,
    String? referenceId,
    String? alternativePhoneNumber,
    bool? hasCourtesyDevice,
    TicketType? ticketType,
    TicketStatus? ticketStatus,
    DateTime? estimatedDeliveryAt,
    bool clearEstimatedDelivery = false,
    TicketResult? ticketResult,
    String? resolutionNotes,
    String? shippingDocumentId,
    CustomerModel? customer,
    String? targetModelName,
    String? sourceModelName,
    String? createdById,
    String? createdByName,
    String? assignedToId,
    String? assignedToName,
    String? includedAccessories,
    ShippingDocumentModel? shippingDocument,
  }) {
    return TicketModel(
      id: id ?? this.id,
      createdAt: createdAt ?? this.createdAt,
      companyId: companyId ?? this.companyId,
      storeId: storeId ?? this.storeId,
      customerId: customerId ?? this.customerId,
      targetModelId: targetModelId ?? this.targetModelId,
      targetSn: targetSn ?? this.targetSn,
      targetPassword: targetPassword ?? this.targetPassword,
      sourceModelId: sourceModelId ?? this.sourceModelId,
      sourceSn: sourceSn ?? this.sourceSn,
      sourcePassword: sourcePassword ?? this.sourcePassword,
      customerPrice: customerPrice ?? this.customerPrice,
      internalCost: internalCost ?? this.internalCost,
      closedAt: closedAt ?? this.closedAt,
      returnedAt: returnedAt ?? this.returnedAt,
      request: request ?? this.request,
      warrantyType: warrantyType ?? this.warrantyType,
      publicNotes: publicNotes ?? this.publicNotes,
      internalNotes: internalNotes ?? this.internalNotes,
      referenceId: referenceId ?? this.referenceId,
      alternativePhoneNumber:
          alternativePhoneNumber ?? this.alternativePhoneNumber,
      hasCourtesyDevice: hasCourtesyDevice ?? this.hasCourtesyDevice,
      ticketType: ticketType ?? this.ticketType,
      ticketStatus: ticketStatus ?? this.ticketStatus,
      estimatedDeliveryAt: clearEstimatedDelivery
          ? null
          : (estimatedDeliveryAt ?? this.estimatedDeliveryAt),
      ticketResult: ticketResult ?? this.ticketResult,
      resolutionNotes: resolutionNotes ?? this.resolutionNotes,
      shippingDocumentId: shippingDocumentId ?? this.shippingDocumentId,
      customer: customer ?? this.customer,
      targetModelName: targetModelName ?? this.targetModelName,
      sourceModelName: sourceModelName ?? this.sourceModelName,
      createdById: createdById ?? this.createdById,
      createdByName: createdByName ?? this.createdByName,
      assignedToId: assignedToId ?? this.assignedToId,
      assignedToName: assignedToName ?? this.assignedToName,
      includedAccessories: includedAccessories ?? this.includedAccessories,
      shippingDocument: shippingDocument ?? this.shippingDocument,
    );
  }

  /// Deserializzazione da Supabase
  factory TicketModel.fromMap(Map<String, dynamic> map) {
    return TicketModel(
      id: map['id'] as String,
      createdAt: map['created_at'] != null
          ? DateTime.parse(map['created_at']).toLocal()
          : null,
      companyId: map['company_id'] as String,
      storeId: map['store_id'] as String?,
      customerId: map['customer_id'] as String?,
      targetModelId: map['target_model_id'] as String?,
      targetSn: map['target_sn'] as String?,
      sourceModelId: map['source_model_id'] as String?,
      sourceSn: map['source_sn'] as String?,
      targetPassword: map['target_password'] as String?,
      sourcePassword: map['source_password'] as String?,
      // Fix per i field numerici di Postgres che potrebbero arrivare come int o double
      customerPrice: (map['customer_price'] as num?)?.toDouble() ?? 0.0,
      internalCost: (map['internal_cost'] as num?)?.toDouble() ?? 0.0,
      closedAt: map['closed_at'] != null
          ? DateTime.parse(map['closed_at']).toLocal()
          : null,
      returnedAt: map['returned_at'] != null
          ? DateTime.parse(map['returned_at']).toLocal()
          : null,
      request: map['request'] as String? ?? '',
      warrantyType: WarrantyType.fromString(map['warranty_type'] as String?),
      publicNotes: map['public_notes'] as String?,
      internalNotes: map['internal_notes'] as String?,
      referenceId: map['reference_id'] as String?,
      alternativePhoneNumber: map['alternative_phone_number'] as String?,
      hasCourtesyDevice: map['has_courtesy_device'] as bool? ?? false,
      ticketType: TicketType.fromString(map['ticket_type'] as String),
      ticketStatus: TicketStatus.fromString(map['ticket_status'] as String),
      estimatedDeliveryAt: map['estimated_delivery_at'] != null
          ? DateTime.parse(map['estimated_delivery_at']).toLocal()
          : null,
      ticketResult: TicketResult.fromString(map['ticket_result'] as String?),
      resolutionNotes: map['resolution_notes'] as String?,
      shippingDocumentId: map['shipping_document_id'] as String?,
      customer: map['customer'] != null
          ? CustomerModel.fromMap(map['customer'] as Map<String, dynamic>)
          : null,
      targetModelName: (map['target_model']?['name_with_brand'] as String?)
          ?.myFormat(),
      sourceModelName: (map['source_model']?['name_with_brand'] as String?)
          ?.myFormat(),
      createdById: map['created_by_id'] as String?,
      createdByName: (map['created_by']?['name'] as String?)?.myFormat(),
      assignedToId: map['assigned_to_id'] as String?,
      assignedToName: (map['assigned_to']?['name'] as String?)?.myFormat(),
      includedAccessories: map['included_accessories'] as String?,
      shippingDocument: map['shipping_document'] != null
          ? ShippingDocumentModel.fromMap(
              map['shipping_document'] as Map<String, dynamic>,
            )
          : null,
    );
  }

  /// Serializzazione per Supabase
  Map<String, dynamic> toMap() {
    return {
      if (id != null) 'id': id,
      'company_id': companyId,
      'store_id': storeId,
      'customer_id': customerId,
      'target_model_id': targetModelId,
      'target_sn': targetSn,
      'source_model_id': sourceModelId,
      'source_sn': sourceSn,
      'target_password': targetPassword,
      'source_password': sourcePassword,

      'customer_price': customerPrice,
      'internal_cost': internalCost,
      if (closedAt != null) 'closed_at': closedAt!.toUtc().toIso8601String(),
      if (returnedAt != null)
        'returned_at': returnedAt!.toUtc().toIso8601String(),
      'request': request,
      'created_by_id': createdById,
      'warranty_type': warrantyType?.value ?? WarrantyType.noWarranty.value,
      'public_notes': publicNotes,
      'internal_notes': internalNotes,
      'reference_id': referenceId,
      'alternative_phone_number': alternativePhoneNumber,
      'has_courtesy_device': hasCourtesyDevice,
      'ticket_type': ticketType.value,
      'ticket_status': ticketStatus.value,
      if (estimatedDeliveryAt != null)
        'estimated_delivery_at': estimatedDeliveryAt!.toUtc().toIso8601String(),
      if (ticketResult != null) 'ticket_result': ticketResult!.value,
      'resolution_notes': resolutionNotes,
      'included_accessories': includedAccessories,
      'shipping_document_id': shippingDocumentId,
    };
  }

  @override
  List<Object?> get props => [
    id,
    createdAt,
    companyId,
    storeId,
    customerId,
    targetModelId,
    targetSn,
    sourceModelId,
    sourceSn,
    targetPassword,
    sourcePassword,
    customerPrice,
    internalCost,
    closedAt,
    returnedAt,
    request,
    warrantyType,
    publicNotes,
    internalNotes,
    alternativePhoneNumber,
    hasCourtesyDevice,
    ticketType,
    ticketStatus,
    estimatedDeliveryAt,
    ticketResult,
    resolutionNotes,
    includedAccessories,
    customer,
    targetModelName,
    sourceModelName,
    createdById,
    createdByName,
    assignedToId,
    assignedToName,
    shippingDocumentId,
    shippingDocument,
  ];
}
