import 'dart:async';

import 'package:be_happy/domain/usecase/get_payment_cards_usecase.dart';
import 'package:be_happy/domain/usecase/get_profile_usecase.dart';
import 'package:be_happy/domain/usecase/get_scooter_order_by_id_usecase.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../core/result.dart';
import '../../../domain/entities/scooter_order.dart';
import '../../../domain/usecase/pay_ride_usecase.dart';
import '../../domain/entities/payment_card.dart';
import '../event/payment_confirm_event.dart';
import '../state/payment_confirm_state.dart';

class PaymentConfirmBloc
    extends Bloc<PaymentConfirmEvent, PaymentConfirmState> {
  final PayRideUsecase _payRideUsecase;
  final GetScooterOrderByIdUsecase _getScooterOrderByIdUsecase;
  final GetPaymentCardsUsecase _getPaymentCardsUsecase;
  final GetProfileUseCase _getProfileUseCase;

  PaymentConfirmBloc(
    this._payRideUsecase,
    this._getScooterOrderByIdUsecase,
    this._getPaymentCardsUsecase,
    this._getProfileUseCase,
  ) : super(const PaymentConfirmState()) {
    on<PayRide>(_onPayRide);
    on<PaymentConfirmStarted>(_onStarted);
    on<PaymentCardChanged>(_onCardChanged);
    on<SelectBalancePressed>(_onSelectBalancePressed);
  }

  Future<void> _onStarted(
    PaymentConfirmStarted event,
    Emitter<PaymentConfirmState> emit,
  ) async {
    emit(state.copyWith(status: PaymentConfirmStatus.loading));

    PaymentCard? mainCard;
    final result = await _getScooterOrderByIdUsecase(event.orderId);
    final cards_result = await _getPaymentCardsUsecase();

    if (cards_result is Success<List<PaymentCard>>) {
      mainCard = cards_result.data?.firstWhere(
        (card) => card.isMain,
        orElse: () => cards_result.data!.first,
      );
    }

    switch (result) {
      case Success<ScooterOrder>(data: final order):
        emit(
          state.copyWith(
            status: PaymentConfirmStatus.initial,
            order: order,
            selectedCard: mainCard,
          ),
        );
        break;
      case Failure<ScooterOrder>():
        emit(
          state.copyWith(
            status: PaymentConfirmStatus.failure,
            errorMessage: 'Не удалось загрузить данные поездки',
          ),
        );
    }
  }

  void _onCardChanged(
    PaymentCardChanged event,
    Emitter<PaymentConfirmState> emit,
  ) {
    emit(state.copyWith(selectedCard: event.card, useBalance: false));
  }

  Future<void> _onPayRide(
    PayRide event,
    Emitter<PaymentConfirmState> emit,
  ) async {
    emit(state.copyWith(status: PaymentConfirmStatus.loading));

    final photoIds = event.photoIds.isEmpty ? [1] : event.photoIds;

    final result = await _payRideUsecase(
      event.orderId,
      event.cardId,
      event.isBalance,
    );

    if (result is Success<void>) {
      emit(
        state.copyWith(
          status: PaymentConfirmStatus.success,
          paymentCompleted: true,
        ),
      );
    } else if (result is Failure) {
      emit(
        state.copyWith(
          status: PaymentConfirmStatus.failure,
          errorMessage: 'Не удалось оплатить поездку',
        ),
      );
    }
  }

  FutureOr<void> _onSelectBalancePressed(
    SelectBalancePressed event,
    Emitter<PaymentConfirmState> emit,
  ) async {
    final profile = await _getProfileUseCase();

    emit(
      state.copyWith(
        useBalance: true,
        userBalance: profile.balance,
        selectedCard: null,
      ),
    );
  }
}
