import 'dart:typed_data';

import 'package:flux/core/blocs/session/session_cubit.dart';
import 'package:flux/features/attachments/blocs/attachments_bloc.dart';
import 'package:flux/features/attachments/data/attachments_repository.dart';
import 'package:flux/features/tickets/models/shipping_document_model.dart';
import 'package:flux/features/master_data/providers/models/provider_model.dart';
import 'package:flux/features/master_data/providers/models/provider_role.dart';
import 'package:flux/features/tickets/models/ticket_model.dart';
import 'package:get_it/get_it.dart';
import 'package:supabase_flutter/supabase_flutter.dart' hide Bucket;

class TicketsShippingRepository {
  final _supabase = GetIt.I.get<SupabaseClient>();
  final _companyId = GetIt.I.get<SessionCubit>().state.company!.id!;

  Future<List<ProviderModel>> fetchRepairCenters() async {
    try {
      final response = await _supabase
          .from('provider')
          .select('*, provider_locations (*)')
          .eq('is_active', true)
          .order('name');

      final allProviders = (response as List)
          .map((row) => ProviderModel.fromMap(row as Map<String, dynamic>))
          .toList();

      // Filtriamo lato client per prendere SOLO i repairCenter
      return allProviders
          .where((p) => p.roles.contains(ProviderRole.repairCenter))
          .toList();
    } catch (e) {
      throw ('Errore caricamento laboratori: $e');
    }
  }

  Future<List<ShippingDocumentModel>> fetchShipmentDocumentsForTicket(
    String ticketId,
  ) async {
    try {
      final response = await _supabase
          .from('shipping_documents')
          .select('*, attachments (*)')
          .contains('ticket_ids', [ticketId]);

      return (response as List)
          .map(
            (row) => ShippingDocumentModel.fromMap(row as Map<String, dynamic>),
          )
          .toList();
    } catch (e) {
      throw ('Errore caricamento documenti di trasporto: $e');
    }
  }

  Future<List<ShippingDocumentModel>> fetchCompanyShipmentDocuments() async {
    try {
      final response = await _supabase
          .from('shipping_documents')
          .select('*, attachments (*)')
          .eq('company_id', _companyId);

      return (response as List)
          .map(
            (row) => ShippingDocumentModel.fromMap(row as Map<String, dynamic>),
          )
          .toList();
    } catch (e) {
      throw ('Errore caricamento documenti di trasporto aziendali: $e');
    }
  }

  Future<ShippingDocumentModel> fetchShipmentDocumentById(
    String documentId,
  ) async {
    try {
      final response = await _supabase
          .from('shipping_documents')
          .select('*, attachments (*)')
          .eq('id', documentId)
          .single();

      return ShippingDocumentModel.fromMap(response);
    } catch (e) {
      throw ('Errore caricamento documento di trasporto: $e');
    }
  }

  /// Salva il DDT nel DB, carica il PDF nello Storage e lo registra come Attachment ufficiale
  Future<void> createShipmentWithPdf({
    required ShippingDocumentModel document,
    required Uint8List pdfBytes,
    required TicketStatus newTicketStatus,
  }) async {
    try {
      final attachmentsRepo = GetIt.I.get<AttachmentsRepository>();

      // 1. Inseriamo prima il Documento di Trasporto (DDT) su Postgres
      // Il modello iniziale non ha ancora gli allegati popolati, quindi passiamo il toMap standard
      final savedDocument = await _supabase
          .from('shipping_documents')
          .insert(document.toMap())
          .select('id')
          .single();

      final documentId = savedDocument['id'] as String;

      // 2. Prepariamo il nome del file PDF (es: DDT_123_2026.pdf)
      final fileName =
          'DDT_${document.docNumber.replaceAll('/', '_').replaceAll(' ', '_')}.pdf';

      // 3. IL TOCCO MASTER: Delegiamo l'upload e la registrazione nel DB all'AttachmentsRepository
      // Questo creerà la riga nella tabella degli allegati agganciando lo 'shipping_document_id'
      await attachmentsRepo.uploadAndRegisterFile(
        parentId: documentId,
        parentType: AttachmentParentType.shippingDocument, // Il tuo nuovo enum!
        companyId: document.companyId,
        bucket: Bucket.companyDocuments,
        rawBytes: pdfBytes,
        rawFileName: fileName,
      );

      // 4. Aggiorniamo lo stato di TUTTI i ticket inclusi nel DDT e li colleghiamo all'ID del DDT
      await _supabase
          .from('ticket')
          .update({
            'ticket_status': newTicketStatus.value,
            'shipping_document_id': documentId,
          })
          .inFilter('id', document.ticketIds);
    } catch (e) {
      throw ('Errore durante il salvataggio e upload della spedizione con allegato: $e');
    }
  }
}
