import 'dart:developer';

import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/payment_models/pay_order_detail_resp_model.dart';
import 'package:mc_common_app/repositories/payments_repo.dart';
import 'package:mc_common_app/services/payments_service.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
import '../classes/app_state.dart';

class PaymentVM extends ChangeNotifier {
  final PaymentService paymentService;
  final PaymentsRepo paymentRepo;

  PaymentVM({required this.paymentService, required this.paymentRepo});

  PaymentMethods selectedPaymentMethod = PaymentMethods.mada;
  PaymentTypes currentPaymentType = PaymentTypes.ads;

  int currentAdId = -1;

  void updateCurrentAdId({required int id}) {
    currentAdId = id;
  }

  int requestId = -1;

  void updateRequestId({required int id}) {
    requestId = id;
  }

  int orderProviderSubscriptionId = -1;

  void updateOrderProviderSubscriptionId({required int id}) {
    orderProviderSubscriptionId = id;
  }

  List<int> appointmentIdsForPayment = [];

  void updateAppointmentIdsForPayment({required List<int> ids}) {
    appointmentIdsForPayment = ids;
  }

  updateSelectedPaymentMethod(PaymentMethods selectedMethod) {
    selectedPaymentMethod = selectedMethod;
    notifyListeners();
  }

  Future<void> onContinuePressed(BuildContext context, {required PaymentTypes paymentType}) async {
    switch (selectedPaymentMethod) {
      case PaymentMethods.mada:
      // TODO: Handle this case.
        break;
      case PaymentMethods.visa:
        await onVisaCardSelected(context, paymentType);
        break;
      case PaymentMethods.applePay:
      // TODO: Handle this case.
        break;
      case PaymentMethods.masterCard:
      // TODO: Handle this case.
        break;
      case PaymentMethods.tamara:
      // TODO: Handle this case.
        break;
    }

    return;
  }

  Future<void> onAdsPaymentSuccess({required BuildContext context, required int currentAdId, required int paymentTypeId}) async {
    Utils.showLoading(context);
    PayOrderDetailRespModel payOrderDetailRespModel = await paymentRepo.getPayOrderDetails(paymentId: paymentTypeId, adId: currentAdId);
    await Future.delayed(const Duration(seconds: 2));
    Utils.hideLoading(context);

    log("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}");

    if (payOrderDetailRespModel.isPaid == null || !payOrderDetailRespModel.isPaid!) {
      Utils.showToast(LocaleKeys.paymentFailed.tr());
      return;
    }

    if (payOrderDetailRespModel.isPaid != null && payOrderDetailRespModel.isPaid!) {
      Utils.showToast(LocaleKeys.paymentSuccessful.tr());
      navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
    }
  }

  Future<void> onAppointmentPaymentSuccess({required BuildContext context, required int currentAdId, required int paymentTypeId}) async {
    Utils.showLoading(context);
    //TODO:  CONFIRM FROM ZAHOOR THAT WILL THIS METHOD WORK FOR APPOINTMENT
    PayOrderDetailRespModel payOrderDetailRespModel = await paymentRepo.getPayOrderDetails(paymentId: paymentTypeId, adId: currentAdId);
    await Future.delayed(const Duration(seconds: 2));
    Utils.hideLoading(context);

    log("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}");

    if (payOrderDetailRespModel.isPaid == null || !payOrderDetailRespModel.isPaid!) {
      Utils.showToast(LocaleKeys.paymentFailed.tr());
      return;
    }

    if (payOrderDetailRespModel.isPaid != null && payOrderDetailRespModel.isPaid!) {
      Utils.showToast(LocaleKeys.paymentSuccessful.tr());
      navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
    }
  }

  int getIdTypeByPaymentType(PaymentTypes paymentTypes) {
    switch (paymentTypes) {
      case PaymentTypes.subscription:
        return orderProviderSubscriptionId;
      case PaymentTypes.appointment:
      case PaymentTypes.partialAppointment:
        return -1;
      case PaymentTypes.request:
        return requestId;
      case PaymentTypes.adReserve:
      case PaymentTypes.ads:
      case PaymentTypes.extendAds:
        return currentAdId;
    }
  }

  Future<void> placeThePayment({required PaymentTypes paymentTypeEnum, required BuildContext context}) async {
    await paymentService.placePayment(
      // This will be request ID for request payment || ad ID for Ad Related Payment || OrderProviderSubscriptionID for SubscriptionPayment
      id: getIdTypeByPaymentType(paymentTypeEnum),
      appointmentIds: appointmentIdsForPayment,
      paymentType: paymentTypeEnum,
      onFailure: () {
        Utils.showToast(LocaleKeys.paymentFailed.tr());
        switch (paymentTypeEnum) {
          case PaymentTypes.subscription:
          // TODO: Handle this case.
            break;
          case PaymentTypes.appointment:
          // TODO: Handle this case.
            log("Appointment Payment has been Failed!!");
            break;
          case PaymentTypes.adReserve:
          // TODO: Handle this case.
            break;
          case PaymentTypes.ads:
          // TODO: Handle this case.
            break;
          case PaymentTypes.request:
          // TODO: Handle this case.
            break;
          case PaymentTypes.extendAds:
          // TODO: Handle this case.
            break;
          case PaymentTypes.partialAppointment:
            log("Partial Appointment Payment has been Failed!!");

            break;
        }
      },
      onSuccess: () async {
        // TOD0: we have to take payment confirmation methods from Backend team and make success callbacks like onAdsPaymentSuccess
        switch (paymentTypeEnum) {
          case PaymentTypes.subscription:
            onSubscriptionSuccess(context);
            break;
          case PaymentTypes.appointment:
            log("Appointment Payment has been Succeeded");
            break;
          case PaymentTypes.request:
            break;
          case PaymentTypes.adReserve:
          case PaymentTypes.ads:
          case PaymentTypes.extendAds:
            await onAdsPaymentSuccess(context: context, paymentTypeId: paymentTypeEnum.getIdFromPaymentTypesEnum(), currentAdId: currentAdId);
            break;
          case PaymentTypes.partialAppointment:
            log("Partial Appointment Payment has been Succeeded");
            break;
        }
      },
    );
  }

  onSubscriptionSuccess(BuildContext context) {
    // pop(context);
    // pop(context);
    // pop(context);

    //  context.read<SubscriptionsVM>().getMySubscriptions(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
    context
        .read<SubscriptionsVM>()
        .mySubscriptionsBySp = [];
    context.read<SubscriptionsVM>().getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
    navigateReplaceWithNameUntilRoute(context, AppRoutes.mySubscriptionsPage);
  }

  Future<void> onVisaCardSelected(BuildContext context, PaymentTypes paymentType) async {
    currentPaymentType = paymentType;
    switch (currentPaymentType) {
      case PaymentTypes.appointment:
      case PaymentTypes.partialAppointment:
        if (appointmentIdsForPayment.isEmpty) return;
        await placeThePayment(context: context, paymentTypeEnum: paymentType);
        break;
      case PaymentTypes.request:
      // TODO: Handle this case.
        break;
      case PaymentTypes.subscription:
        await placeThePayment(context: context, paymentTypeEnum: paymentType);
        break;
      case PaymentTypes.ads:
      case PaymentTypes.adReserve:
      case PaymentTypes.extendAds:
        if (currentAdId == -1) return;
        await placeThePayment(context: context, paymentTypeEnum: paymentType);
        break;
    }
  }
}
