import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';

import '../../models/scan_history_model.dart';
import '../../repositories/scan_history_repository.dart';

part 'scan_history_event.dart';
part 'scan_history_state.dart';

class ScanHistoryBloc extends Bloc<ScanHistoryEvent, ScanHistoryState> {
  final ScanHistoryRepository _repository;

  ScanHistoryBloc({ScanHistoryRepository? repository})
      : _repository = repository ?? ScanHistoryRepository(),
        super(ScanHistoryInitial()) {
    on<FetchScanHistoryEvent>(_onFetchScanHistory);
    on<RefreshScanHistoryEvent>(_onRefreshScanHistory);
    on<UpdateScanHistoryDateEvent>(_onUpdateDate);
    on<UpdateScanHistoryStatusEvent>(_onUpdateStatus);
    on<SearchScanHistoryEvent>(_onSearchScanHistory);
    on<SelectScanHistoryEvent>(_onSelectScanHistory);
    on<ClearSelectedScanHistoryEvent>(_onClearSelectedScanHistory);
  }

  // ─── Fetch ────────────────────────────────────────────────────────────────

  Future<void> _onFetchScanHistory(
    FetchScanHistoryEvent event,
    Emitter<ScanHistoryState> emit,
  ) async {
    DateTime? selectedDate = event.clearDate ? null : (event.date ?? state.selectedDate);
    String selectedStatus = event.status ?? state.selectedStatus;

    emit(ScanHistoryLoading(
      selectedDate: selectedDate,
      selectedStatus: selectedStatus,
    ));

    try {
      String? formattedDate;
      if (selectedDate != null) {
        formattedDate = DateFormat('yyyy-MM-dd').format(selectedDate);
      }
      
      final List<ScanHistory> items = await _repository.fetchScanHistory(
        date: formattedDate,
        status: selectedStatus,
      );
      emit(ScanHistoryLoaded(
        allItems: items,
        filteredItems: items,
        selectedDate: selectedDate,
        selectedStatus: selectedStatus,
      ));
    } catch (e) {
      emit(ScanHistoryError(
        errorMessage: e.toString(),
        selectedDate: selectedDate,
        selectedStatus: selectedStatus,
      ));
    }
  }

  // ─── Refresh ──────────────────────────────────────────────────────────────

  Future<void> _onRefreshScanHistory(
    RefreshScanHistoryEvent event,
    Emitter<ScanHistoryState> emit,
  ) async {
    if (state is! ScanHistoryLoaded) return;
    
    final currentState = state as ScanHistoryLoaded;
    emit(currentState.copyWith(isRefreshing: true));

    try {
      String? formattedDate;
      if (currentState.selectedDate != null) {
        formattedDate = DateFormat('yyyy-MM-dd').format(currentState.selectedDate!);
      }
      
      final List<ScanHistory> items = await _repository.fetchScanHistory(
        date: formattedDate,
        status: currentState.selectedStatus,
      );
      emit(ScanHistoryLoaded(
        allItems: items,
        filteredItems: items,
        selectedDate: currentState.selectedDate,
        selectedStatus: currentState.selectedStatus,
      ));
    } catch (e) {
      emit(ScanHistoryError(
        errorMessage: e.toString(),
        selectedDate: currentState.selectedDate,
        selectedStatus: currentState.selectedStatus,
      ));
    }
  }

  // ─── Update Filters ───────────────────────────────────────────────────────

  Future<void> _onUpdateDate(
    UpdateScanHistoryDateEvent event,
    Emitter<ScanHistoryState> emit,
  ) async {
    add(FetchScanHistoryEvent(
      date: event.date,
      clearDate: event.date == null,
      status: state.selectedStatus,
    ));
  }

  Future<void> _onUpdateStatus(
    UpdateScanHistoryStatusEvent event,
    Emitter<ScanHistoryState> emit,
  ) async {
    add(FetchScanHistoryEvent(
      date: state.selectedDate,
      status: event.status,
    ));
  }

  // ─── Search ───────────────────────────────────────────────────────────────

  void _onSearchScanHistory(
    SearchScanHistoryEvent event,
    Emitter<ScanHistoryState> emit,
  ) {
    List<ScanHistory> allItems = [];
    String query = event.query.trim().toLowerCase();

    if (state is ScanHistoryLoaded) {
      allItems = (state as ScanHistoryLoaded).allItems;
    } else if (state is ScanHistoryDetailState) {
      allItems = (state as ScanHistoryDetailState).allItems;
    } else {
      return;
    }

    final filtered = query.isEmpty
        ? allItems
        : allItems.where((item) {
            return item.customerName.toLowerCase().contains(query) ||
                item.customerEmail.toLowerCase().contains(query) ||
                item.bookingNumber.toLowerCase().contains(query) ||
                item.attractionTitle.toLowerCase().contains(query) ||
                item.status.toLowerCase().contains(query) ||
                item.cardType.toLowerCase().contains(query);
          }).toList();

    if (state is ScanHistoryLoaded) {
      emit((state as ScanHistoryLoaded).copyWith(
        filteredItems: filtered,
        searchQuery: event.query,
      ));
    } else if (state is ScanHistoryDetailState) {
      final s = state as ScanHistoryDetailState;
      emit(ScanHistoryDetailState(
        selectedItem: s.selectedItem,
        allItems: s.allItems,
        filteredItems: filtered,
        searchQuery: event.query,
        selectedDate: s.selectedDate,
        selectedStatus: s.selectedStatus,
      ));
    }
  }

  // ─── Select Detail ────────────────────────────────────────────────────────

  void _onSelectScanHistory(
    SelectScanHistoryEvent event,
    Emitter<ScanHistoryState> emit,
  ) {
    if (state is ScanHistoryLoaded) {
      final s = state as ScanHistoryLoaded;
      emit(ScanHistoryDetailState(
        selectedItem: event.selectedItem,
        allItems: s.allItems,
        filteredItems: s.filteredItems,
        searchQuery: s.searchQuery,
        selectedDate: s.selectedDate,
        selectedStatus: s.selectedStatus,
      ));
    }
  }

  // ─── Clear / Back ─────────────────────────────────────────────────────────

  void _onClearSelectedScanHistory(
    ClearSelectedScanHistoryEvent event,
    Emitter<ScanHistoryState> emit,
  ) {
    if (state is ScanHistoryDetailState) {
      final s = state as ScanHistoryDetailState;
      emit(ScanHistoryLoaded(
        allItems: s.allItems,
        filteredItems: s.filteredItems,
        searchQuery: s.searchQuery,
        selectedDate: s.selectedDate,
        selectedStatus: s.selectedStatus,
      ));
    }
  }
}