import 'dart:convert';
import 'package:SEFER/constant/api_key.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/controller/functions/tts.dart';
import 'package:SEFER/controller/payment/paymob/paymob_response.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:flutter_paypal/flutter_paypal.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:get/get.dart';
import 'package:local_auth/local_auth.dart';
import 'package:SEFER/controller/home/map_passenger_controller.dart';

import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/info.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../functions/crud.dart';
import '../functions/toast.dart';
import 'paymob/paymob_wallet.dart';

class PaymentController extends GetxController {
  bool isLoading = false;
  bool isWalletChecked = true;
  bool isCashChecked = false;
  bool isWalletFound = false;
  bool isPromoSheetDialogue = false;
  final formKey = GlobalKey<FormState>();
  final promo = TextEditingController();
  double totalPassenger = Get.find<MapPassengerController>().totalPassenger;
  int? selectedAmount = 0;
  List<dynamic> totalPassengerWalletDetails = [];
  String passengerTotalWalletAmount = '';
  String ip = '1';
  DateTime now = DateTime.now();
  late int timestamp;

  void updateSelectedAmount(int value) {
    selectedAmount = value;
    update();
  }

  void changePromoSheetDialogue() {
    isPromoSheetDialogue = !isPromoSheetDialogue;
    update();
  }

  getPassengerWallet() async {
    isLoading = true;
    update();

    await CRUD().get(
        link: AppLink.getWalletByPassenger,
        payload: {'passenger_id': box.read(BoxName.passengerID)}).then((value) {
      box.write(BoxName.passengerWalletTotal,
          jsonDecode(value)['message'][0]['total'].toString());
    });
    isLoading = false;
    update();
  }

  addPassengerWallet() async {
    isLoading = true;
    update();
    // double sallaryAccountNowBeforeAdding =
    //     double.parse(box.read(BoxName.passengerWalletTotal).toString());
    await CRUD().post(link: AppLink.addPassengersWallet, payload: {
      'passenger_id': box.read(BoxName.passengerID).toString(),
      'balance': selectedAmount.toString()
    }).then((value) {
      getPassengerWallet();
      // sallaryAccountNowBeforeAdding = sallaryAccountNowBeforeAdding +
      //     double.parse(selectedAmount.toString());
      // box.write(BoxName.passengerWalletTotal, sallaryAccountNowBeforeAdding);
    });

    isLoading = false;
    update();
  }

  void onChangedPaymentMethodWallet(bool? value) {
    if (box.read(BoxName.passengerWalletTotal) == null ||
        double.parse(box.read(BoxName.passengerWalletTotal).toString()) <
            totalPassenger) {
      isWalletChecked = false;
      isWalletChecked ? isCashChecked = true : isCashChecked = true;
      update();
    } else {
      isWalletChecked = !isWalletChecked;
      isWalletChecked ? isCashChecked = false : isCashChecked = true;
      update();
    }
  }

  void onChangedPaymentMethodCash(bool? value) {
    if (box.read(BoxName.passengerWalletTotal) == null ||
        double.parse(box.read(BoxName.passengerWalletTotal)) < totalPassenger) {
      isWalletChecked = false;
      isCashChecked = !isCashChecked;
      isCashChecked ? isWalletChecked = false : isWalletChecked = false;
      update();
    } else {
      isCashChecked = !isCashChecked;
      isCashChecked ? isWalletChecked = false : isWalletChecked = true;
      update();
    }
  }

  void applyPromoCodeToPassenger() async {
    //TAWJIHI
    CRUD().get(link: AppLink.getPassengersPromo, payload: {
      'promo_code': promo.text,
    }).then((value) {
      var decod = jsonDecode(value);

      if (decod["status"] == "success") {
        print(totalPassenger);
        var firstElement = decod["message"][0];
        totalPassenger = totalPassenger -
            (totalPassenger * int.parse(firstElement['amount']));
        MapPassengerController().promoTaken = true;
        update();
        print(totalPassenger);
      }
    });
  }

  late String clientSecret;

  Future<void> makePaymentStripe(
      double amount, String currency, Function method) async {
    var newAmount = (amount * 100).toInt();

    try {
      // Check if local authentication is available
      bool isAvailable = await LocalAuthentication().isDeviceSupported();
      if (isAvailable) {
        // Authenticate the user
        bool didAuthenticate = await LocalAuthentication().authenticate(
          localizedReason: 'Use Touch ID or Face ID to confirm payment',
        );
        if (didAuthenticate) {
          // User authenticated successfully, proceed with payment
          clientSecret = await getClientSecret(newAmount.toString(), currency);
          await initializePaymentSheet(clientSecret);
          await Stripe.instance.presentPaymentSheet();
          method();
        } else {
          // Authentication failed, handle accordingly
          print('Authentication failed');
        }
      } else {
        // Local authentication not available, proceed with payment without authentication
        clientSecret = await getClientSecret(newAmount.toString(), currency);
        await initializePaymentSheet(clientSecret);
        await Stripe.instance.presentPaymentSheet();
        method();
      }
    } catch (e) {
      rethrow;
    }
  }

  Future<void> initializePaymentSheet(String clientSecret) async {
    await Stripe.instance.initPaymentSheet(
      paymentSheetParameters: SetupPaymentSheetParameters(
        // intentConfiguration: IntentConfiguration.fromJson({}),
        // applePay: const PaymentSheetApplePay(merchantCountryCode: 'US'),
        // googlePay: const PaymentSheetGooglePay(merchantCountryCode: 'US'),
        paymentIntentClientSecret: clientSecret,
        merchantDisplayName: AppInformation.appName,
        billingDetails: BillingDetails(
            name: box.read(BoxName.nameDriver) == null
                ? box.read(BoxName.name).toString()
                : box.read(BoxName.nameDriver).toString(),
            email: box.read(BoxName.emailDriver) == null
                ? box.read(BoxName.email).toString()
                : box.read(BoxName.emailDriver).toString(),
            phone: box.read(BoxName.phoneDriver) == null
                ? box.read(BoxName.phone).toString()
                : box.read(BoxName.phoneDriver).toString(),
            address: Address(
                city: 'city',
                country: box.read(BoxName.countryCode), //'United States'
                line1: '',
                line2: '',
                postalCode: '12345',
                state: box.read(BoxName.countryCode) // 'Boston'
                )),
        allowsDelayedPaymentMethods: true,
        customerEphemeralKeySecret: Stripe.merchantIdentifier,
        appearance: const PaymentSheetAppearance(
          shapes: PaymentSheetShape(borderRadius: 12),
          colors: PaymentSheetAppearanceColors(
            background: AppColor.secondaryColor,
          ),
        ),
        billingDetailsCollectionConfiguration:
            const BillingDetailsCollectionConfiguration(
          name: CollectionMode.automatic,
          phone: CollectionMode.automatic,
          email: CollectionMode.automatic,
          // address: CollectionMode.automatic,
        ),
      ),
    );
  }

  Future<String> getClientSecret(String amount, currency) async {
    var res = await CRUD().postStripe(
      link: 'https://api.stripe.com/v1/payment_intents',
      payload: {
        'amount': amount,
        'currency': currency,
        'payment_method_types[0]': 'card'
      },
    );

    // Convert the res object to a JSON object
    final jsonResponse = jsonDecode(res);
    print(jsonResponse);
    // Check if the client_secret property exists and is not null
    if (jsonResponse.containsKey('client_secret') &&
        jsonResponse['client_secret'] != null) {
      // Return the client_secret property
      return jsonResponse['client_secret'] as String;
    } else {
      throw Exception('Failed to fetch client secret');
    }
  }

  Future<void> configure3dSecureFuture() async {
    await Stripe.instance.openApplePaySetup();
  }

  Future<void> makePaymentPayPal(BuildContext context) async {
    try {
      // Check if local authentication is available
      bool isAvailable = await LocalAuthentication().isDeviceSupported();
      if (isAvailable) {
        // Authenticate the user
        bool didAuthenticate = await LocalAuthentication().authenticate(
          localizedReason: 'Use Touch ID or Face ID to confirm payment',
        );
        if (didAuthenticate) {
          // User authenticated successfully, proceed with payment

          if (selectedAmount != 0) {
            print(selectedAmount);
            changePromoSheetDialogue();
            Navigator.of(context).push(
              MaterialPageRoute(
                builder: (BuildContext context) => UsePaypal(
                    sandboxMode: true,
                    clientId: AK.payPalClientId,
                    secretKey: AK.payPalSecret,
                    returnURL: AppInformation.website,
                    cancelURL: "${AppInformation.website}/cancel",
                    transactions: [
                      {
                        "amount": {
                          //sb-opsju26682403@personal.example.com
                          "total": '$selectedAmount',
                          "currency": box.read(BoxName.countryCode) == 'Egypt'
                              ? 'EGP'
                              : "JOD",
                          "details": {
                            "subtotal": '$selectedAmount',
                            "shipping": '0',
                            "shipping_discount": 0
                          }
                        },
                        "description": "The payment transaction description.",
                        "payment_options": const {
                          "allowed_payment_method": "INSTANT_FUNDING_SOURCE"
                        },
                        "item_list": {
                          "items": [
                            {
                              "name": "${AppInformation.appName} Wallet ",
                              "quantity": 1,
                              "price": '$selectedAmount',
                              "currency": "USD"
                            }
                          ],

                          // shipping address is not required though
                          "shipping_address": const {
                            "recipient_name":
                                "${AppInformation.appName} Wallet",
                            "line1": "Shafa Badran",
                            "line2": "",
                            "city": "Amman",
                            "country_code": "JO",
                            "postal_code": "13112",
                            "phone": "+962798583052",
                            "state": "Amman"
                          },
                        }
                      }
                    ],
                    note: "Contact us for any questions on your order.".tr,
                    onSuccess: (Map params) async {
                      print("onSuccess: $params");
                      addPassengerWallet();
                      changePromoSheetDialogue();
                      await getPassengerWallet();
                    },
                    onError: (error) {
                      print("onError: $error");
                      Toast.show(context, ' $error'.tr, AppColor.redColor);
                    },
                    onCancel: (params) {
                      print('cancelled: $params');
                      Toast.show(context, 'Pyament Cancelled .'.tr,
                          AppColor.yellowColor);
                    }),
              ),
            );
          } else {
            Toast.show(context, 'You will choose one of above !'.tr,
                AppColor.redColor);
          }
        } else {
          // Authentication failed, handle accordingly
          print('Authentication failed');
        }
      }
    } catch (e) {
      rethrow;
    }
  }

  Map licenseDetailsMap = {};
  Future getLicenseInfo() async {
    var res = await CRUD().get(
        link: AppLink.getLicense,
        payload: {'driverID': box.read(BoxName.driverID)});
    licenseDetailsMap = jsonDecode(res);
    // print(licenseDetailsMap['message'][0]['name']);
  }

  Future createConnectAccount() async {
    String url = 'https://api.stripe.com/v1/accounts';
    await getLicenseInfo();
    DateTime dob =
        DateTime.parse(licenseDetailsMap['message'][0]['dateOfBirth']);
    int currentTimestamp =
        (DateTime.now().millisecondsSinceEpoch / 1000).round();
    print('Current Unix timestamp: $currentTimestamp');
    int day = dob.day;
    int month = dob.month;
    int year = dob.year;
    await getIpAddress();
    final body = {
      "type": "custom",
      "business_profile[name]": box.read(BoxName.nameDriver),
      "business_profile[product_description]": "Captain",
      "business_profile[support_address][city]": "San Francisco",
      "business_profile[support_address][country]": 'US',
      "business_profile[support_address][line1]":
          licenseDetailsMap['message'][0]['address'].toString().trim()[0],
      "business_profile[support_address][postal_code]":
          licenseDetailsMap['message'][0]['postalCode'],
      "business_profile[support_address][state]": "MA",
      "business_profile[support_email]": "support@sefer.live",
      "business_profile[support_phone]": "555-123-4567",
      "business_profile[url]": "https://sefer.live",
      "business_type": "individual",
      "capabilities[card_payments][requested]": "true",
      "capabilities[transfers][requested]": "true",
      "company[address][city]": "ATTLEBORO",
      "company[address][country]": "US",
      "company[address][line1]": "1249 NEWPORT AVE",
      "company[address][postal_code]": "02703 ",
      "company[address][state]": "MA",
      "company[name]": AppInformation.companyName,
      "country": "us",
      "default_currency": "usd",
      "email": "support@sefer.live",
      // "individual[ssn]": "123-45-6789", //
      "individual[id_number]": licenseDetailsMap['message'][0]['documentNo'],
      // "individual[id_type]": "drivers_license", //
      "individual[address][city]": "ATTLEBORO",
      "individual[address][country]": "US",
      "individual[address][line1]": licenseDetailsMap['message'][0]['address'],
      // "individual[address][postal_code]": licenseDetailsMap['message'][0]
      // ['postalCode'],
      "individual[address][state]": "MA",
      // "individual[ssn_last_4]": '1111', ////////
      "individual[dob][day]": day.toString(),
      "individual[dob][month]": month.toString(),
      "individual[dob][year]": year.toString(),
      "individual[email]": box.read(BoxName.emailDriver),
      "individual[first_name]":
          licenseDetailsMap['message'][0]['name'].toString().split(' ')[0],
      "individual[gender]":
          licenseDetailsMap['message'][0]['sex'] == 'M' ? 'male' : 'female',
      "individual[last_name]":
          licenseDetailsMap['message'][0]['name'].toString().split(' ')[1],
      // "individual[phone]": box.read(BoxName.phoneDriver),////////////
      "tos_acceptance[date]": currentTimestamp.toString(),
      "tos_acceptance[ip]": ip.toString()
    };

    final response = await CRUD().postStripe(
      link: url,
      payload: body,
    );
    final responseData = jsonDecode(response);
    // print(responseData);
    final accountId = responseData['id'];
    box.write(BoxName.accountIdStripeConnect, accountId);
    await updateCaptainAccountBank();
    print('accountId = $accountId');
    return accountId;
  }

  Future updateCaptainAccountBank() async {
    var res = await CRUD().post(link: AppLink.updateAccountBank, payload: {
      'id': box.read(BoxName.driverID),
      'accountBank': box.read(BoxName.accountIdStripeConnect),
    });
    if (jsonDecode(res)['status'] == 'success') {
      Get.snackbar('Account Updated', '');
    }
  }

  Future<String> createTransactionToCaptain(
      String amount, String account) async {
    String url = 'https://api.stripe.com/v1/transfers';

    final body = {
      'amount': amount, //amount
      'currency': 'usd',
      'destination': account //'acct_1OKIjQRgcWrsdyDT' //account id
    };

    final response = await CRUD().postStripe(
      link: url,
      payload: body,
    );
    final responseData = jsonDecode(response);
    print(responseData);
    final transactionId = responseData['id'];

    print('transactionId = $transactionId');
    return transactionId;
  }

  Future getIpAddress() async {
    var url = Uri.parse('https://api.ipify.org?format=json');

    var response = await http.get(url);

    if (response.statusCode == 200) {
      ip = jsonDecode(response.body)['ip'];
      print(ip);
    } else {
      print('Request failed with status: ${response.statusCode}');
    }
  }

// 'https://accept.paymob.com/unifiedcheckout/?publicKey=egy_pk_live_mbjDC9Ni6FSHKmsz8sOHiVk2xd7oWRve&clientSecret=egy_sk_live_c0904e9cf04506ae64f818d4e075b4a957e3713fdf7a22cb7da30a29e72442b5'

  Future<void> payWithPayMob(
      BuildContext context, String amount, currency, Function method) async {
    String newAmount = (double.parse(amount) * 100).toStringAsFixed(2);
    try {
      bool isAvailable = await LocalAuthentication().isDeviceSupported();
      if (isAvailable) {
        // Authenticate the user
        bool didAuthenticate = await LocalAuthentication().authenticate(
          localizedReason: 'Use Touch ID or Face ID to confirm payment',
        );
        if (didAuthenticate) {
          final PaymobResponse? response = await PaymobPayment.instance.pay(
            context: context,
            currency: currency, //"EGP",
            amountInCents: newAmount, // 19.00 EGP

            billingData: PaymobBillingData(),
            onPayment: (PaymobResponse response) {
              print('Success: ${response.success}');
              print('Transaction ID: ${response.transactionID}');
              print('Response Code: ${response.responseCode}');
              // print('Message: ${response.message}');
              print(box.read(BoxName.passengerWalletTotal));
              print(box.read(BoxName.name));
              print(box.read(BoxName.phone));
              // print();
            },
          );

          if (response!.responseCode == 'APPROVED') {
            Get.defaultDialog(
              barrierDismissible: false,
              title: 'Payment Successful'.tr,
              titleStyle: AppStyle.title,
              content: Text(
                'The payment was approved.'.tr,
                style: AppStyle.title,
              ),
              confirm: MyElevatedButton(
                title: 'OK'.tr,
                kolor: AppColor.greenColor,
                onPressed: () async {
                  Get.back();
                  method();
                },
              ),
            );
          } else {
            Get.defaultDialog(
              barrierDismissible: false,
              // backgroundColor: AppColor.redColor,
              title: 'Payment Failed'.tr,
              content: Text(
                'The payment was not approved. Please try again.'.tr,
                textAlign: TextAlign.center,
                style: AppStyle.title,
              ),
              confirm: MyElevatedButton(
                title: 'OK'.tr,
                kolor: AppColor.redColor,
                onPressed: () async {
                  Get.back();
                },
              ),
            );
          }
        } else {
          // Authentication failed, handle accordingly
          print('Authentication failed');
        }
      } else {
        final PaymobResponse? response = await PaymobPayment.instance.pay(
          context: context,
          currency: currency, //"EGP",
          amountInCents: newAmount, // 19.00 EGP
          billingData: PaymobBillingData(),
          onPayment: (PaymobResponse response) {
            // print('Success: ${response.success}');
            // print('Transaction ID: ${response.transactionID}');
            // print('Response Code: ${response.responseCode}');
            // print('Message: ${response.message}');
          },
        );

        if (response!.responseCode == 'APPROVED') {
          Get.defaultDialog(
            barrierDismissible: false,
            title: 'Payment Successful'.tr,
            titleStyle: AppStyle.title,
            // backgroundColor: AppColor.greenColor,
            content: Text(
              'The payment was approved.'.tr,
              style: AppStyle.title,
            ),
            confirm: MyElevatedButton(
              kolor: AppColor.greenColor,
              title: 'OK'.tr,
              onPressed: () async {
                Get.back();
                method();
              },
            ),
          );
        } else {
          Get.defaultDialog(
            barrierDismissible: false,
            // backgroundColor: AppColor.redColor,
            title: 'Payment Failed'.tr,
            content: Column(
              children: [
                IconButton(
                  onPressed: () {
                    Get.find<TextToSpeechController>().speakText(
                      'The payment was not approved. Please try again.'.tr,
                    );
                  },
                  icon: const Icon(Icons.headphones),
                ),
                Text(
                  'The payment was not approved. Please try again.'.tr,
                  textAlign: TextAlign.center,
                  style: AppStyle.title,
                ),
                Text(
                  '${'The reason is'.tr} ${response.message!.tr}',
                  textAlign: TextAlign.center,
                  style: AppStyle.title.copyWith(color: AppColor.redColor),
                ),
              ],
            ),
            confirm: MyElevatedButton(
              title: 'OK'.tr,
              kolor: AppColor.redColor,
              onPressed: () async {
                Get.back();
              },
            ),
          );
        }
      }
    } catch (e) {
      Get.defaultDialog(
        title: 'Error'.tr,
        content: Text(
          'An error occurred during the payment process.'.tr,
          style: AppStyle.title,
        ),
      );
      rethrow;
    }
  }

  Future<void> payWithPayMobWallet(
      BuildContext context, String amount, currency, Function method) async {
    String newAmount = (double.parse(amount) * 100).toStringAsFixed(2);
    try {
      bool isAvailable = await LocalAuthentication().isDeviceSupported();
      if (isAvailable) {
        // Authenticate the user
        bool didAuthenticate = await LocalAuthentication().authenticate(
          localizedReason: 'Use Touch ID or Face ID to confirm payment',
        );
        if (didAuthenticate) {
          final PaymobResponseWallet? response =
              await PaymobPaymentWallet.instance.pay(
            context: context,
            currency: currency, //"EGP",
            amountInCents: newAmount, // 19.00 EGP

            billingData: PaymobBillingDataWallet(),
            onPayment: (PaymobResponseWallet response) {
              // print('Success: ${response.success}');
              // print('Transaction ID: ${response.transactionID}');
              // print('Response Code: ${response.responseCode}');
              // print('Message: ${response.message}');

              // print(box.read(BoxName.passengerWalletTotal));//
              // print(box.read(BoxName.name));
              // print(box.read(BoxName.phone));
              // print();
            },
          );

          if (response!.success == true && response.responseCode == '200') {
            Get.defaultDialog(
              barrierDismissible: false,
              title: 'Payment Successful'.tr,
              titleStyle: AppStyle.title,
              content: Text(
                'The payment was approved.'.tr,
                style: AppStyle.title,
              ),
              confirm: MyElevatedButton(
                title: 'OK'.tr,
                kolor: AppColor.greenColor,
                onPressed: () async {
                  Get.back();
                  method();
                },
              ),
            );
          } else {
            Get.defaultDialog(
              barrierDismissible: false,
              // backgroundColor: AppColor.redColor,
              title: 'Payment Failed'.tr,
              content: Column(
                children: [
                  IconButton(
                    onPressed: () {
                      Get.find<TextToSpeechController>().speakText(
                        'The payment was not approved. Please try again.'.tr,
                      );
                    },
                    icon: const Icon(Icons.headphones),
                  ),
                  Text(
                    'The payment was not approved. Please try again.'.tr,
                    textAlign: TextAlign.center,
                    style: AppStyle.title,
                  ),
                  Text(
                    '${'The reason is'.tr} ${response.message!.tr}',
                    textAlign: TextAlign.center,
                    style: AppStyle.title.copyWith(color: AppColor.redColor),
                  ),
                ],
              ),
              confirm: MyElevatedButton(
                title: 'OK'.tr,
                kolor: AppColor.redColor,
                onPressed: () async {
                  Get.back();
                },
              ),
            );
          }
        } else {
          // Authentication failed, handle accordingly
          print('Authentication failed');
        }
      } else {
        final PaymobResponse? response = await PaymobPayment.instance.pay(
          context: context,
          currency: currency, //"EGP",
          amountInCents: newAmount, // 19.00 EGP
          billingData: PaymobBillingData(),
          onPayment: (PaymobResponse response) {
            // print('Success: ${response.success}');
            // print('Transaction ID: ${response.transactionID}');
            // print('Response Code: ${response.responseCode}');
            // print('Message: ${response.message}');
          },
        );

        if (response!.responseCode == 'APPROVED') {
          Get.defaultDialog(
            barrierDismissible: false,
            title: 'Payment Successful'.tr,
            titleStyle: AppStyle.title,
            // backgroundColor: AppColor.greenColor,
            content: Text(
              'The payment was approved.'.tr,
              style: AppStyle.title,
            ),
            confirm: MyElevatedButton(
              kolor: AppColor.greenColor,
              title: 'OK'.tr,
              onPressed: () async {
                Get.back();
                method();
              },
            ),
          );
        } else {
          Get.defaultDialog(
            barrierDismissible: false,
            // backgroundColor: AppColor.redColor,
            title: 'Payment Failed'.tr,
            content: Text(
              'The payment was not approved. Please try again.'.tr,
              textAlign: TextAlign.center,
              style: AppStyle.title,
            ),
            confirm: MyElevatedButton(
              title: 'OK'.tr,
              kolor: AppColor.redColor,
              onPressed: () async {
                Get.back();
              },
            ),
          );
        }
      }
    } catch (e) {
      Get.defaultDialog(
        title: 'Error'.tr,
        content: Text(
          'An error occurred during the payment process.'.tr,
          style: AppStyle.title,
        ),
      );
      rethrow;
    }
  }

  @override
  void onInit() {
    timestamp = now.millisecondsSinceEpoch;
    if (box.read(BoxName.passengerWalletTotal) == null) {
      box.write(BoxName.passengerWalletTotal, '0');
    }
    getPassengerWallet();
    final localAuth = LocalAuthentication();
    super.onInit();
  }
}
