import 'dart:developer';

import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.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/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/ad_view_model.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_provider.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.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;
    log("appointmentIdsForPayment: ${appointmentIdsForPayment}");
  }

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

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

    return;
  }

  Future<void> verifyPayments(
      {required BuildContext context, required int id, List<int>? appointmentIds, required int paymentTypeId, required Function() onVerified, bool isForAppointment = false}) async {
    try {
      Utils.showLoading(context);
      bool isPaid = await paymentRepo.verifyPayment(
        paymentTypeId: paymentTypeId,
        id: id,
        isForAppointments: isForAppointment,
        appointmentIds: appointmentIds,
      );
      Utils.hideLoading(context);

      // TODO: VERIFY THIS WITH ZAHOOR
      if (!isPaid) {
        // Utils.showToast(LocaleKeys.paymentFailed.tr());
        // pop(context);
        return;
      } else {
        Utils.showToast(LocaleKeys.paymentSuccessful.tr());
      }
      onVerified();
    } catch (e) {
      Utils.showToast(e.toString());
      return;
    }
  }

  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(
      id: getIdTypeByPaymentType(paymentTypeEnum),
      // This will be request ID for request payment || ad ID for Ad Related Payment || OrderProviderSubscriptionID for SubscriptionPayment
      appointmentIds: appointmentIdsForPayment,
      paymentType: paymentTypeEnum,
      onFailure: () {
        Utils.showToast(LocaleKeys.paymentFailed.tr());
        switch (paymentTypeEnum) {
          case PaymentTypes.subscription:
          case PaymentTypes.appointment:
          case PaymentTypes.adReserve:
          case PaymentTypes.ads:
          case PaymentTypes.request:
          case PaymentTypes.extendAds:
          case PaymentTypes.partialAppointment:
            break;
        }
      },
      onSuccess: () async {
        Utils.showToast("Verifying Payment..");

        switch (paymentTypeEnum) {
          case PaymentTypes.subscription:
            await verifyPayments(
              context: context,
              paymentTypeId: paymentTypeEnum.getIdFromPaymentTypesEnum(),
              id: orderProviderSubscriptionId,
              onVerified: () => onSubscriptionPaymentSuccess(context),
            );
            break;

          case PaymentTypes.appointment:
          case PaymentTypes.partialAppointment:
            await verifyPayments(
              id: 0,
              isForAppointment: true,
              appointmentIds: appointmentIdsForPayment,
              context: context,
              paymentTypeId: paymentTypeEnum.getIdFromPaymentTypesEnum(),
              onVerified: () => onAppointmentSuccess(context),
            );
            break;

          case PaymentTypes.request:
            await verifyPayments(
              context: context,
              paymentTypeId: paymentTypeEnum.getIdFromPaymentTypesEnum(),
              id: requestId,
              onVerified: () => onRequestPaymentSuccess(context),
            );
            break;

          case PaymentTypes.adReserve:
          case PaymentTypes.ads:
          case PaymentTypes.extendAds:
            await verifyPayments(
              context: context,
              paymentTypeId: paymentTypeEnum.getIdFromPaymentTypesEnum(),
              id: currentAdId,
              onVerified: () => onAdsPaymentSuccess(context),
            );
        }
      },
    );
  }

  void onRequestPaymentSuccess(BuildContext context) {
    if (AppState().currentAppType == AppType.provider) {
      context.read<DashboardVMProvider>().onNavbarTapped(4);
    } else {
      context.read<DashboardVmCustomer>().onNavbarTapped(4);
    }
    navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
  }

  void onAdsPaymentSuccess(BuildContext context) {
    context.read<AdVM>().updateIsExploreAds(false);
    if (AppState().currentAppType == AppType.provider) {
      context.read<DashboardVMProvider>().onNavbarTapped(3);
      context.read<AdVM>().applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.active);
    } else {
      context.read<DashboardVmCustomer>().onNavbarTapped(3);
      context.read<AdVM>().applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.pendingForPost);
    }
    navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard, arguments: DashboardRouteEnum.fromAdsPayment);
  }

  void onSubscriptionPaymentSuccess(BuildContext context) {
    pop(context);
    // context.read<SubscriptionsVM>().getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
    navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
  }

  void onAppointmentSuccess(BuildContext context) {
    if (AppState().currentAppType == AppType.provider) {
      context.read<DashboardVMProvider>().onNavbarTapped(1);
    } else {
      context.read<DashboardVmCustomer>().onNavbarTapped(1);
    }
    navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
  }

  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:
        if (requestId == -1) return;
        await placeThePayment(context: context, paymentTypeEnum: paymentType);
        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;
    }
  }
}
