import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flux/core/blocs/session/session_cubit.dart';
import 'package:flux/features/customers/models/customer_model.dart';
import 'package:flux/features/master_data/staff/models/staff_member_model.dart';
import 'package:flux/features/tickets/models/ticket_model.dart';
import 'package:flux/features/tickets/data/ticket_repository.dart';
import 'package:flux/features/tracking/data/tracking_repository.dart';
import 'package:flux/features/tracking/models/tracking_model.dart';
import 'package:get_it/get_it.dart';
import 'ticket_form_state.dart';

class TicketFormCubit extends Cubit<TicketFormState> {
  final TicketRepository _repository = GetIt.I.get<TicketRepository>();
  final SessionCubit _sessionCubit = GetIt.I.get<SessionCubit>();

  // Costruttore: prepariamo subito il ticket base con i dati di chi lo crea
  TicketFormCubit({StaffMemberModel? createdBy, TicketModel? existingTicket})
    : super(
        TicketFormState(
          // Se c'è un ticket esistente usa quello, ALTRIMENTI ne crea uno vuoto
          // e ci stampa subito il nome del creatore!
          ticket:
              existingTicket ??
              TicketModel.empty().copyWith(
                createdById: createdBy?.id,
                createdByName: createdBy?.name,
              ),
        ),
      );

  /// 1. INIZIALIZZAZIONE
  Future<void> initForm({String? id, TicketModel? existingTicket}) async {
    if (existingTicket != null) {
      // SCENARIO 1: Abbiamo il ticket intero passato via record
      emit(
        state.copyWith(ticket: existingTicket, status: TicketFormStatus.ready),
      );
    } else if (id != null) {
      // SCENARIO 2: QR CODE o Web Refresh! (Hai solo l'ID)
      emit(state.copyWith(status: TicketFormStatus.loading));

      try {
        // Boom! Lo scarica dal database in tempo reale
        final fetchedTicket = await _repository.getTicketById(id);
        emit(
          state.copyWith(ticket: fetchedTicket, status: TicketFormStatus.ready),
        );
      } catch (e) {
        emit(
          state.copyWith(
            status: TicketFormStatus.failure,
            errorMessage: 'Ticket non trovato',
          ),
        );
      }
    } else {
      // SCENARIO 3: Nuovo Ticket
      final currentStore = _sessionCubit.state.currentStore;
      final companyId = _sessionCubit.state.company?.id ?? '';

      // IL TRUCCO È QUI: Usiamo `state.ticket` invece di `TicketModel.empty()`.
      // `state.ticket` HA GIÀ i dati di 'createdBy' settati nel costruttore!
      final newTicket = state.ticket.copyWith(
        companyId: companyId,
        storeId: currentStore?.id,
        ticketStatus: TicketStatus.open, // <-- O il tuo status di default
        ticketType: TicketType.repair,
      );

      emit(state.copyWith(ticket: newTicket, status: TicketFormStatus.ready));
    }
  }

  /// 2. AGGIORNAMENTO CLIENTE (Usato dal nostro SharedCustomerSection!)
  void updateCustomer(CustomerModel customer) {
    emit(
      state.copyWith(
        ticket: state.ticket.copyWith(
          customerId: customer.id,
          customer: customer,
          alternativePhoneNumber:
              state.ticket.alternativePhoneNumber ?? customer.phoneNumber,
        ),
      ),
    );
  }

  /// 3. AGGIORNAMENTO MODELLO (Usato dal nostro SharedModelSection!)
  void updateTargetModel({required String modelId, required String modelName}) {
    emit(
      state.copyWith(
        ticket: state.ticket.copyWith(
          targetModelId: modelId,
          targetModelName: modelName,
        ),
      ),
    );
  }

  void updateSourceModel({required String modelId, required String modelName}) {
    emit(
      state.copyWith(
        ticket: state.ticket.copyWith(
          sourceModelId: modelId,
          sourceModelName: modelName,
        ),
      ),
    );
  }

  void updateCreator({required String staffId, required String staffName}) {
    emit(
      state.copyWith(
        ticket: state.ticket.copyWith(
          createdById: staffId,
          createdByName: staffName,
        ),
      ),
    );
  }

  /// 4. AGGIORNAMENTO GENERICO DEI CAMPI
  void updateFields({
    TicketType? ticketType,
    TicketStatus? status,
    String? request,
    String? targetSn,
    String? targetPassword,
    String? sourceSn,
    String? sourcePassword,
    String? alternativePhoneNumber,
    bool? hasCourtesyDevice,
    String? includedAccessories,
    String? publicNotes,
    String? internalNotes,
    double? customerPrice,
    double? internalCost,
    String? assignedToId,
    String? assignedToName,
    WarrantyType? warrantyType,
    DateTime? estimatedDeliveryAt,
    bool clearEstimatedDelivery = false,
  }) {
    emit(
      state.copyWith(
        ticket: state.ticket.copyWith(
          ticketType: ticketType ?? state.ticket.ticketType,
          ticketStatus: status ?? state.ticket.ticketStatus,
          request: request ?? state.ticket.request,
          targetSn: targetSn ?? state.ticket.targetSn,
          targetPassword: targetPassword ?? state.ticket.targetPassword,
          sourcePassword: sourcePassword ?? state.ticket.sourcePassword,
          sourceSn: sourceSn ?? state.ticket.sourceSn,
          alternativePhoneNumber:
              alternativePhoneNumber ?? state.ticket.alternativePhoneNumber,
          hasCourtesyDevice:
              hasCourtesyDevice ?? state.ticket.hasCourtesyDevice,
          includedAccessories:
              includedAccessories ?? state.ticket.includedAccessories,
          publicNotes: publicNotes ?? state.ticket.publicNotes,
          internalNotes: internalNotes ?? state.ticket.internalNotes,
          customerPrice: customerPrice ?? state.ticket.customerPrice,
          internalCost: internalCost ?? state.ticket.internalCost,
          assignedToId: assignedToId ?? state.ticket.assignedToId,
          assignedToName: assignedToName ?? state.ticket.assignedToName,
          warrantyType: warrantyType ?? state.ticket.warrantyType,
          estimatedDeliveryAt: estimatedDeliveryAt,
          clearEstimatedDelivery: clearEstimatedDelivery,
        ),
      ),
    );
  }

  /// 5. SALVATAGGIO
  Future<void> saveTicket() async {
    emit(state.copyWith(status: TicketFormStatus.saving));

    try {
      final ticketToSave = state.ticket;

      // Validazione base
      if (ticketToSave.customerId == null || ticketToSave.customerId!.isEmpty) {
        throw Exception("Seleziona un cliente prima di salvare.");
      }
      TicketModel? savedTicket;
      if (ticketToSave.id == null) {
        savedTicket = await _repository.insertTicket(ticketToSave);
      } else {
        savedTicket = await _repository.updateTicket(ticketToSave);
      }
      emit(
        state.copyWith(
          status: TicketFormStatus.success,
          ticket: ticketToSave.copyWith(
            id: savedTicket.id,
            referenceId: savedTicket.referenceId,
          ),
        ),
      );
    } catch (e) {
      emit(
        state.copyWith(
          status: TicketFormStatus.failure,
          errorMessage: e.toString(),
        ),
      );
    }
  }

  /// 5.1 SALVATAGGIO SILENZIOSO (Per generare il QR Code al volo)
  Future<String?> saveTicketDraft() async {
    // Non mettiamo lo stato 'saving' per non far sfarfallare tutta la UI,
    // usiamo un caricamento invisibile.
    try {
      final ticketToSave = state.ticket;

      if (ticketToSave.customerId == null || ticketToSave.customerId!.isEmpty) {
        throw Exception("Seleziona un cliente prima di poter usare il QR.");
      }

      final savedTicket = await _repository.insertTicket(ticketToSave);

      // Aggiorniamo silenziosamente lo stato con il ticket che ora ha un ID!
      emit(state.copyWith(ticket: savedTicket, status: TicketFormStatus.ready));

      return savedTicket.id;
    } catch (e) {
      emit(
        state.copyWith(
          status: TicketFormStatus.failure,
          errorMessage: e.toString(),
        ),
      );
      return null;
    }
  }

  Future<void> takeInCharge({
    required String staffId,
    required String staffName,
  }) async {
    final currentTicket = state.ticket;

    // Sicurezza: non possiamo prendere in carico un ticket fantasma
    if (currentTicket.id == null || currentTicket.id!.isEmpty) return;

    // 1. Prepariamo il ticket aggiornato
    final updatedTicket = currentTicket.copyWith(
      ticketStatus: TicketStatus
          .inProgress, // Assumendo che tu abbia un enum per gli stati
      assignedToId: staffId,
      assignedToName: staffName,
    );

    try {
      // 2. Aggiorniamo il ticket sul Database (usa il tuo metodo esistente del repo)
      await _repository.updateTicket(updatedTicket);

      // 3. Spara il log automatico nella Timeline!
      await GetIt.I.get<TrackingRepository>().logQuickEvent(
        companyId: currentTicket.companyId,
        message: "Ticket preso in carico. Inizio lavorazione.",
        type: TrackingType.statusChange,
        parentId: currentTicket.id!,
        parentType: TrackingParentType.ticket,
        staffId: staffId,
        // Lo mettiamo pubblico (isInternal: false) così il cliente a casa vede che
        // il suo dispositivo è ufficialmente sotto i ferri!
        isInternal: false,
      );

      // 4. Aggiorniamo lo stato locale del Cubit per far scattare la UI
      emit(state.copyWith(ticket: updatedTicket));
    } catch (e) {
      // Gestisci eventuali errori (es. mostrando una snackbar)
      emit(
        state.copyWith(
          status: TicketFormStatus.failure,
          errorMessage: 'Errore durante la presa in carico: $e',
        ),
      );
    }
  }

  Future<void> pauseTicket({
    required TicketStatus newStatus,
    required String notes,
  }) async {
    final currentTicket = state.ticket;
    if (currentTicket.id == null || currentTicket.id!.isEmpty) return;

    // 1. Usiamo lo stato esatto scelto dal tecnico
    final updatedTicket = currentTicket.copyWith(ticketStatus: newStatus);

    try {
      await _repository.updateTicket(updatedTicket);

      // 2. Componiamo un bel messaggio per la Timeline
      // Es: "Sospeso per: waitingForQuote. Note: Cliente in ferie"
      String timelineMessage = "Lavorazione sospesa (${newStatus.name}).";
      if (notes.isNotEmpty) {
        timelineMessage += " Note: $notes";
      }

      await GetIt.I.get<TrackingRepository>().logQuickEvent(
        companyId: currentTicket.companyId,
        message: timelineMessage,
        type: TrackingType.statusChange,
        parentId: currentTicket.id!,
        parentType: TrackingParentType.ticket,
        staffId: currentTicket.assignedToId ?? '',
        isInternal: false,
      );

      emit(state.copyWith(ticket: updatedTicket));
    } catch (e) {
      emit(
        state.copyWith(
          status: TicketFormStatus.failure,
          errorMessage: 'Errore durante la sospensione: $e',
        ),
      );
    }
  }

  Future<void> completeTicket({
    required TicketResult result,
    required double finalPrice,
  }) async {
    final currentTicket = state.ticket;

    if (currentTicket.id == null || currentTicket.id!.isEmpty) return;

    // 1. Aggiorniamo il ticket con il nuovo status, l'esito e il prezzo!
    final updatedTicket = currentTicket.copyWith(
      ticketStatus: TicketStatus.ready,
      ticketResult: result,
      customerPrice: finalPrice,
    );

    try {
      await _repository.updateTicket(updatedTicket);

      // 2. Timeline personalizzata in base all'esito
      final esitoTesto = result == TicketResult.success
          ? "Riparato con successo"
          : "Non riparabile/Preventivo rifiutato";

      await GetIt.I.get<TrackingRepository>().logQuickEvent(
        companyId: currentTicket.companyId,
        message:
            "Lavorazione completata. Esito: $esitoTesto. Il dispositivo è pronto per il ritiro.",
        type: TrackingType.statusChange,
        parentId: currentTicket.id!,
        parentType: TrackingParentType.ticket,
        staffId: currentTicket.assignedToId ?? '',
        isInternal: false,
      );

      emit(state.copyWith(ticket: updatedTicket));
    } catch (e) {
      emit(
        state.copyWith(
          status: TicketFormStatus.failure,
          errorMessage: 'Errore durante la chiusura: $e',
        ),
      );
    }
  }

  Future<void> deleteTicket() async {
    final currentTicket = state.ticket;

    if (currentTicket.id == null || currentTicket.id!.isEmpty) return;

    try {
      await _repository.deleteTicket(currentTicket.id!);
      emit(state.copyWith(status: TicketFormStatus.deleted));
    } catch (e) {
      emit(
        state.copyWith(
          status: TicketFormStatus.failure,
          errorMessage: 'Errore durante l\'eliminazione: $e',
        ),
      );
    }
  }
}
