import 'package:concierge/data/remote/models/order.dart';
import 'package:concierge/domain/models/app_error.dart';
import 'package:concierge/domain/repositories/property_repository.dart';
import 'package:concierge/presentation/app/cart_cubit.dart';
import 'package:concierge/presentation/app/concierge_cubit.dart';
import 'package:concierge/presentation/base/base_cubit.dart';
import 'package:concierge/presentation/screens/payment/bloc/payment_state.dart';
import 'package:payment_plugin/payment_plugin.dart';
import 'package:payment_plugin/utils/json.dart';
import 'package:payment_plugin/presentation/app/bloc/payment_cubit.dart' as payment_plugin;

class PaymentCubit extends BaseCubit<PaymentState> {
  final CartCubit _cartCubit;
  final ConciergeCubit _conciergeCubit;
  final PropertyRepository _propertyRepository;
  final PaymentPlugin _paymentPlugin;
  final payment_plugin.PaymentCubit _paymentCubit;

  PaymentCubit(
    this._cartCubit,
    this._conciergeCubit,
    this._propertyRepository,
    this._paymentPlugin,
    this._paymentCubit,
  ) : super(const PaymentState()) {
    init();
    _paymentCubit.stream.listen((state) {
      if (state is PaymentProcessingStateConfirmed) {
        _checkStatus();
      }
    });
  }

  Future<void> init() async {
    try {
      safeEmit(state.copyWith(isLoading: true, error: AppError.none));
      final products = _cartCubit.state.productsWithQuantity.values.map(
        (product) => {
          "id": product.productId,
          "quantity": product.quantity,
          "options": [
            ...product.variant.entries.map(
              (entry) => {
                "id": entry.key,
                "answers": [
                  {
                    "id": entry.value,
                    "is_selected": true,
                  },
                ],
              },
            ),
          ],
        },
      );
      final area = _cartCubit.state.selectedArea!;
      final orderResponse = await _propertyRepository.createOrder(
        products: products.toList(),
        areaId: area.id,
        roomNumber: _conciergeCubit.state.roomNumber,
        isDelivery: _cartCubit.state.isDelivery,
        locationCode: _cartCubit.state.deliveryLocationCode,
        deliveryLocation: _cartCubit.state.deliveryLocation,
        readyTime: _cartCubit.state.readyTime,
        comment: _cartCubit.state.comment,
        chargeToRoom: _cartCubit.state.chargeToRoom,
      );
      safeEmit(state.copyWith(orderId: orderResponse.id));
      if (orderResponse.totalPrice > 0 || _cartCubit.state.chargeToRoom) {
        final sessionResponse = await _paymentPlugin.repository.createAdyenSessionForConcierge(
          orderResponse.id,
        );
        final data = Json.of(sessionResponse);
        final clientKey = data["clientKey"];
        final session = Json.of(data["sessionResponse"]);
        final sessionData = session["sessionData"];
        final sessionId = session["id"];
        await _paymentCubit.createConciergeSession(sessionId, clientKey, sessionData);
      } else {
        _checkStatus();
      }
    } catch (e, st) {
      handleError(e, st);
      safeEmit(state.copyWith(error: AppError.unknown(e.toString())));
      _paymentCubit.emitError(e);
    } finally {
      safeEmit(state.copyWith(isLoading: false));
    }
  }

  Future<void> _checkStatus() async {
    try {
      final response = await _propertyRepository.getOrder(state.orderId);
      if (response.status == OrderStatus.received) {
        safeEmit(state.copyWith(paymentSuccess: true));
      } else if (response.status == OrderStatus.cancelled) {
        _paymentCubit.emitError("Operation cancelled");
      } else {
        await Future.delayed(Duration(seconds: 1));
        _checkStatus();
      }
    } catch (e, st) {
      _paymentCubit.emitError(e);
      handleError(e, st);
    }
  }
}