import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
import 'dart:async';
import 'dart:convert' as convert;
import 'package:http_auth/http_auth.dart';
import 'package:provider/provider.dart';
import '../../../providers/payment_key_provider.dart';

class PaypalServices {
  // String domain = "https://api.sandbox.paypal.com"; // for sandbox mode
  String domain = "https://api.paypal.com"; // for production mode

  // change clientId and secret with your own, provided by paypal
  String clientId = "";
  String secret = "";

  // for getting the access token from Paypal
  Future<String?> getAccessToken(BuildContext context) async {
    clientId = Provider.of<PaymentKeyProvider>(context, listen: false)
        .paymentKeyModel!
        .paypalClientId!;
    secret = Provider.of<PaymentKeyProvider>(context, listen: false)
        .paymentKeyModel!
        .paypalSecretId!;

    try {
      var client = BasicAuthClient(clientId, secret);
      Response response = await client.post(
          Uri.parse('$domain/v1/oauth2/token?grant_type=client_credentials'));
      if (response.statusCode == 200) {
        final body = convert.jsonDecode(response.body);
        return body["access_token"];
      }
      return null;
    } catch (e) {
      rethrow;
    }
  }

  // for creating the payment request with Paypal
  Future<Map<String, String?>?> createPaypalPayment(
      transactions, accessToken) async {
    try {
      var response = await http.post(Uri.parse("$domain/v1/payments/payment"),
          body: convert.jsonEncode(transactions),
          headers: {
            "content-type": "application/json",
            'Authorization': 'Bearer ' + accessToken
          });

      final body = convert.jsonDecode(response.body);
      if (response.statusCode == 201) {
        if (body["links"] != null && body["links"].length > 0) {
          List links = body["links"];

          String? executeUrl = "";
          String? approvalUrl = "";
          final item = links.firstWhere((o) => o["rel"] == "approval_url",
              orElse: () => null);
          if (item != null) {
            approvalUrl = item["href"];
          }
          final item1 = links.firstWhere((o) => o["rel"] == "execute",
              orElse: () => null);
          if (item1 != null) {
            executeUrl = item1["href"];
          }
          return {"executeUrl": executeUrl, "approvalUrl": approvalUrl};
        }
        return null;
      } else {
        throw Exception(body["message"]);
      }
    } catch (e) {
      rethrow;
    }
  }

  // for executing the payment transaction
  Future<List<String>?> executePayment(url, payerId, accessToken) async {
    try {
      var response = await http.post(Uri.parse(url),
          body: convert.jsonEncode({"payer_id": payerId}),
          headers: {
            "content-type": "application/json",
            'Authorization': 'Bearer ' + accessToken
          });

      final body = convert.jsonDecode(response.body);
      if (response.statusCode == 200) {
        var saleId =
            "${body['transactions'][0]['related_resources'][0]['sale']['id']}";
        List<String> ls = ["${body['id']}", saleId];
        return ls;
      }
      return null;
    } catch (e) {
      rethrow;
    }
  }
}
