import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:exide_crr/utils/miscellaneous.dart';
import 'package:exide_crr/constants/app_constants.dart';
import 'package:exide_crr/controller/base_controller.dart';
import 'package:exide_crr/data/app_env.dart';
import 'package:exide_crr/preferences/app_shared_preferences.dart';
import 'package:exide_crr/serverRequest/app_exception.dart';
import 'package:exide_crr/utils/custom_toast.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

import '../appLocalization/language_key.dart';
import '../model/verifyOtp.dart';

final httpClient = http.Client();

class AllHttpRequest {
  static String? apiUrl = AppEnvironment.baseApiUrl;

  static String? baseUrlForSendOtp = "https://http.myvfirst.com/smpp";
  static String? smsData =
      "The OTP to get your Free Exide Sunday Ro of Top Solar Solution Proposal is";

  Map<String, String> formDataHeader = {
    "Content-type": "application/x-www-form-urlencoded"
  };
  Map<String, String> jsonHeader = {"Content-type": "application/json"};

  Future login({body, funcName}) async {
    // set up POST request arguments
    String url = '${AllHttpRequest.apiUrl!}$funcName';
    Map<String, String>? headers = {"Content-type": "application/json"};

    log("URL : $url");
    log("Request : $body");
    // make POST request
    Uri uri = Uri.parse(url);
    var response =
        await http.post(uri, headers: headers, body: json.encode(body));

    log("Response : ${response.body}");
    return json.decode(response.body);
    // if (response.statusCode == 200) {
    //   // var result = json.decode(response.body);
    //   // var now = DateTime.now();
    //   return json.decode(response.body);
    //   // return true;
    // } else {
    //   log("Response Failed===");
    //   return false;
    // }
  }

  Future postUnAuthRequest({body, functionName}) async {
    // set up POST request arguments
    String url = '${AllHttpRequest.apiUrl!}$functionName';
    Map<String, String>? headers = {"Content-type": "application/json"};

    log("URL : $url");
    log("Request : $body");
    // make POST request
    Uri uri = Uri.parse(url);
    var response =
        await http.post(uri, headers: headers, body: json.encode(body));

    log("Response : ${response.body}");
    return json.decode(response.body);
  }

  Future submitSignUp(paramBody) async {
    // set up POST request arguments
    String url = '${AllHttpRequest.apiUrl!}signup';
    Map<String, String>? headers = {"Content-type": "application/json"};

    // make POST request
    Uri uri = Uri.parse(url);
    var response = await http.post(uri, headers: headers, body: paramBody);

    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON.

      var result = json.decode(response.body);

      if (result['user_id'] != 'None') {
        final SharedPreferences prefs = await SharedPreferences.getInstance();
        prefs.setString('user_id', result['user_id']);
        prefs.setString('User_name', result['username']);
        prefs.setString('First_name', result['first_name']);
        prefs.setString('Last_name', result['last_name']);
        prefs.setString('Email_ID', result['Email_ID']);
        prefs.setString('Session_token', result['Session_token']);
        prefs.setString('Role', result['role']);
        /*var tempCoins = result['coins'].toInt();
          prefs.setInt('Coins', tempCoins);*/
        prefs.setDouble('Coins', result['coins']);

        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }

  /// Send otp api calls
  late GetToken generatedAuth;

  Future generateAuth() async {
    try {
      ///Generate authorization token for send otp
      String url = '$baseUrlForSendOtp/api/sendsms/token?action=generate';

      String basicAuth = 'Basic ${base64.encode(utf8.encode('${AppConstants.username}:${AppConstants.password}'))}';
      Map<String, String>? headers = {
        "Content-type": "application/json",
        "Authorization": basicAuth
      };
      Uri uri = Uri.parse(url);
      // make POST request
      var response = await http.post(uri, headers: headers);
      if (response.statusCode == 200) {
        /// If the call to the server was successful, parse the JSON.
        generatedAuth = GetToken.fromJson(jsonDecode(response.body));

        ///Use generatedAuth to send SMS
        sendOtp();
      } else {
        Fluttertoast.showToast(msg: apiError.tr);
        log("Error generate auth--${response.statusCode}");
        throw Error();
      }
    } catch (e) {
      Fluttertoast.showToast(msg: apiError.tr);
      log("Error generate auth--$e");
      throw Error();
    }
  }

  Future sendOtp() async {
    try {
      final baseController = Get.find<BaseController>();

      ///Locally generated 4 digit otp
      baseController.generatedOtp.value = Miscellaneous.generateOTP();

      ///Static smsData along with generated otp
      var smsContent='$smsData ${baseController.generatedOtp.value} -EXIDE';

      ///Set up POST request arguments
      String url = '$baseUrlForSendOtp/sendsms?to=${baseController.userPhoneNumber}&from=ExideB&text=$smsContent';
      Map<String, String>? headers = {
        "Content-type": "application/json",
        "Authorization": "Bearer ${generatedAuth.token}",
      };
      Uri uri = Uri.parse(url);
      var response = await http.post(uri, headers: headers);

      if (response.statusCode == 200) {
      ///If success do nothing
      } else {
        Fluttertoast.showToast(msg: apiError.tr);
        log("Error generate auth--${response.statusCode}");
        throw Error();
      }
    } catch (e) {
      Fluttertoast.showToast(msg: apiError.tr);
      log("Error generate auth--$e");
      throw Error();
    }
  }

  ///

  Future postSubmit({funName, body}) async {
    // String? accessToken = await PreferenceHelper.getToken();
    String? accessToken =
        await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken);

    log("accessToken-==$accessToken");

    // set up POST request arguments
    String url = '${AllHttpRequest.apiUrl!}$funName';
    Map<String, String> headers = {
      "Content-type": "application/json",
      "Authorization": "Bearer $accessToken",
    };

    // make POST request
    log("Url : $url");
    log("Body : $body");
    var response = await http.post(Uri.parse(url),
        headers: headers, body: json.encode(body));
    log("Response $funName: ${response.body}}");
    log("Status Code===${response.statusCode}}");
    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON.
      var jsonResponse = json.decode(response.body);
      return jsonResponse;
    } else if (response.statusCode == 400) {
      // If the call to the server request parameter missing, parse the JSON.
      var jsonResponse = json.decode(response.body);
      return jsonResponse;
    } else if (response.statusCode == 401) {
      var refreshResponse = await getNewToken();
      return refreshResponse;
    } else {
      return {"message": "Something went wrong!!"};
    }
  }

  Future<http.Response> deleteAnswer(funName, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? userId = prefs.getString('user_id');
    final String? sessionToken = prefs.getString('Session_token');

    // set up POST request arguments
    String url = AllHttpRequest.apiUrl! + funName;
    Map<String, String>? headers = {
      "Content-type": "application/json",
      'user-id': userId!,
      "session-token": sessionToken!,
    };

    // make POST request
    log("Url : $url");
    // log("Headers : $headers");
    // log("Body : $body");
    Uri uri = Uri.parse(url);
    var response = await http.delete(uri, headers: headers);
    log("response : ${response.body}");
    return response;
  }

  Future patchSubmit(funName, body, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? userId = prefs.getString('user_id');
    final String? sessionToken = prefs.getString('Session_token');

    // set up PATCH request arguments
    String url = AllHttpRequest.apiUrl! + funName;
    Map<String, String>? headers = {
      "Content-type": "application/json",
      'user-id': userId!,
      "session-token": sessionToken!,
    };
    Uri uri = Uri.parse(url);
    // make POST request
    var response = await http.patch(uri, headers: headers, body: body);
    return response;
  }

  Future newGetRequest(funName, id) async {
    // set up Get request arguments
    final String url = AllHttpRequest.apiUrl! + funName;
    Map<String, String>? headers = {'answer_id': id};

    log("Url : $url");
    // log("headers : $headers");
    Uri uri = Uri.parse(url);
    // make GET request
    var response = await http.get(uri, headers: headers);
    log("response : ${response.body}");

    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON.

      return json.decode(response.body);
    } else {
      return false;
    }
  }

  Future getRequest1({funName}) async {
    String? accessToken = await PreferenceHelper.getToken();
    // String? accessToken = await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken);

    log("accessToken-==$accessToken");

    String url = '${AllHttpRequest.apiUrl!}$funName';
    Map<String, String> headers = {
      "Authorization": "Bearer $accessToken",
    };

    log("headers-==$headers");

    log("Url : $url");
    Uri uri = Uri.parse(url);
    // make GET request
    var response = await http.get(uri, headers: headers);

    // log("Response $funName: ${response.body}}");
    log("Status Code===${response.statusCode}}");
    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON.
      var jsonResponse = json.decode(response.body);
      return jsonResponse;
    } else if (response.statusCode == 500) {
      return null;
    } else {
      // navigatorKey.currentState!.pushAndRemoveUntil(
      //           SlideRightRoute(
      //             page: MultiBlocProvider(
      //               providers: [
      //                 BlocProvider(create: (_) => AuthenticationBloc(authenticationRepository: AuthenticationRepository()),),
      //                 BlocProvider(create: (_) => PasswordVisibilityBloc(),),
      //                 BlocProvider(create: (_) => CommonFocusListenerBloc(),)
      //               ],
      //               child: const LoginScreen(),
      //             ),
      //           ),
      //           ModalRoute.withName(LoginScreen.tag)
      //       );
      return {};
    }
  }

  Future getRequest({funName}) async {
    // String? accessToken = await PreferenceHelper.getToken();
    String? accessToken =
        await PreferenceHelper.getPreferenceData(PreferenceHelper.accessToken);

    // log("accessToken-==$accessToken");

    String url = '${AllHttpRequest.apiUrl!}$funName';
    Map<String, String> headers = {
      "Authorization": "Bearer $accessToken",
    };

    log("headers-==$headers");

    log("Url : $url");
    Uri uri = Uri.parse(url);
    // make GET request
    var response = await http.get(uri, headers: headers);

    // var response = await TokenMiddleware.refreshTokenMiddleware(
    //     httpClient,
    //     http.Request('GET', uri)
    // );

    // log("Response $funName: ${response.body}}");
    log("Status Code===${response.statusCode}}");
    log("ResponseDataType===${response.runtimeType}}");
    log("ResponseData1111===${response.body}}");
    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON.
      var jsonResponse = json.decode(response.body);
      return jsonResponse;
    } else if (response.statusCode == 401) {
      var refreshResponse = await getNewToken();
      return refreshResponse;
    } else if (response.statusCode == 500) {
      return null;
    } else {
      return {};
    }
  }

  Future getPostRequestWithParam(funName, body, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? userId = prefs.getString('user_id');
    final String? sessionToken = prefs.getString('Session_token');

    // set up Get request arguments
    final String url = AllHttpRequest.apiUrl! + funName;
    Map<String, String>? headers = {
      "Content-type": "application/json",
      'user-id': userId ?? '',
      "session-token": sessionToken ?? '',
    };

    log("URL : $url");
    // log("Headers: $headers");
    log("Body: $body");
    Uri uri = Uri.parse(url);
    // make POST request
    var response = await http.post(uri, headers: headers, body: body);

    log("Response: ${response.body}");

    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      return false;
    }
  }

  Future uploadFiles(
      String apiEndpoint, String filePath, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? sessionToken = prefs.getString('Session_token');
    log("URL : $apiEndpoint");
    var request = http.MultipartRequest(
        'POST', Uri.parse(AllHttpRequest.apiUrl! + apiEndpoint));
    request.headers.addAll({
      'session-token': sessionToken!,
      'Content-Type': 'multipart/form-data',
    });
    log("Headers : ${request.headers}");
    final file = await http.MultipartFile.fromPath("resource", filePath);
    request.files.add(file);
    log("Request : ${request.files.first.field}");

    try {
      final streamedResponse = await request.send();
      final response = await http.Response.fromStream(streamedResponse);
      log("Response : $response");
      if (response.statusCode == 200 || response.statusCode == 201) {
        final responseData = json.decode(response.body);
        log("Response : $responseData");
        return responseData;
      } else {
        return null;
      }
    } catch (e) {
      return null;
    }
  }

  ////////////////Patch method/////////////////////
  Future getPatchRequestWithParam(funName, body, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? sessionToken = prefs.getString('Session_token');

    // set up Get request arguments
    final String url = AllHttpRequest.apiUrl! + funName;
    Map<String, String>? headers = {
      "Content-type": "application/json",
      "session-token": sessionToken!,
    };
    Uri uri = Uri.parse(url);
    // make POST request
    var response = await http.patch(uri, headers: headers, body: body);

    return json.decode(response.body);
//
//    if (response.statusCode == 200) {
//      return json.decode(response.body);
//    } else {
//      return false;
//    }
  }

  Future uploadResource(funName, image, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? sessionToken = prefs.getString('Session_token');

    var request = http.MultipartRequest(
        'POST', Uri.parse(AllHttpRequest.apiUrl! + funName));
    request.headers.addAll({
      'session-token': sessionToken!,
      'Content-Type': 'multipart/form-data',
    });

    var pic = await http.MultipartFile.fromPath("resource", image.path);
    //add multipart to request
    request.files.add(pic);

    try {
      var streamResponse = await request.send();
      var responseData = await streamResponse.stream.bytesToString();
      var resultData = json.decode(responseData);
      return resultData;
    } catch (e) {
      return null;
    }
  }

  // Future<dynamic> uploadResourceWithProgress(
  //     {required url,
  //     required String screenName,
  //     required String resourcePath,
  //     required Function(int bytesCount, int totalLength)
  //         onUploadProgress}) async {
  //   dynamic responseJson;
  //   try {
  //     final SharedPreferences prefs = await SharedPreferences.getInstance();
  //     final String? userId = prefs.getString('user_id');
  //     final String? sessionToken = prefs.getString('Session_token');
  //     Map<String, MultipartFile> requestBody = {};
  //     MultipartFile multiPartFile = await MultipartFile.fromFile(resourcePath);
  //     requestBody.putIfAbsent('resource', () => multiPartFile);
  //     log("URL : ${apiUrl! + url}");
  //     log("Multipart Request : $requestBody");
  //     Dio dio = Dio();
  //     FormData formData = FormData.fromMap(requestBody);
  //     var response = await dio.post(apiUrl! + url,
  //         data: formData,
  //         options: Options(headers: {
  //           'user-id': userId!,
  //           'session-token': sessionToken!,
  //           'Content-Type': 'multipart/form-data',
  //         }),
  //         onSendProgress: onUploadProgress);
  //
  //     responseJson = returnDioResponse(response);
  //   } on SocketException {
  //     throw FetchDataException(AppConstants.internetError);
  //   }
  //   return responseJson;
  // }

  Future postDataSubmit(funName, body, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? sessionToken = prefs.getString('Session_token');

    // set up POST request arguments
    String url = AllHttpRequest.apiUrl! + funName;

    Map<String, String>? headers = {
      "Content-type": "application/json",
      "session-token": sessionToken!,
    };
    Uri uri = Uri.parse(url);
    // make POST request
    var response = await http.post(uri, headers: headers, body: body);
    return response;
  }

  Future getPatchRequestWithUserParam(funName, body, String screenName) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    final String? sessionToken = prefs.getString('Session_token');
    final String? userId = prefs.getString('user_id');

    // set up Get request arguments
    final String url = AllHttpRequest.apiUrl! + funName;
    Map<String, String>? headers = {
      "Content-type": "application/json",
      "user-id": userId!,
      "session-token": sessionToken!,
    };
    Uri uri = Uri.parse(url);
    // make POST request
    var response = await http.patch(uri, headers: headers, body: body);

    return response;
    // if (response.statusCode == 200) {
    //   return json.decode(response.body);
    // } else {
    //   return false;
    // }
  }

  // dynamic returnDioResponse(Response<dynamic> response) {
  //   log("Response ${response.statusCode} : ${response.data}");
  //   switch (response.statusCode) {
  //     case 200:
  //       return response.data;
  //     case 201:
  //       return response.data;
  //     case 400:
  //       throw BadRequestException(response.data['message']);
  //     case 401:
  //       {
  //         // if (responseJson["message"] == "Session Expired") {
  //         //   setLocalStorageValues();
  //         // }
  //         throw UnauthorisedException(response.data['message']);
  //       }
  //     case 403:
  //       throw UnauthorisedException(response.data['message']);
  //     case 500:
  //     default:
  //       throw FetchDataException(response.data['message'] ??
  //           '${AppConstants.communicationError} : ${response.statusCode}');
  //   }
  // }

  dynamic returnResponse(http.Response response) {
    logRequest(response);
    var responseJson = json.decode(response.body.toString());
    switch (response.statusCode) {
      case 200:
        return responseJson;
      case 201:
        return responseJson;
      case 400:
        throw BadRequestException(responseJson['message']);
      case 401:
        {
          // if (responseJson["message"] == "Session Expired") {
          //   setLocalStorageValues();
          // }
          throw UnauthorisedException(responseJson['message']);
        }
      case 403:
        throw UnauthorisedException(responseJson['message']);
      case 500:
      default:
        throw FetchDataException(responseJson['message'] ??
            ' Error occurred while Communication with Server with StatusCode : ${response.statusCode}');
    }
  }

  void logRequest(http.Response response) {
    // show api logs
    log("Response ${response.statusCode} : ${response.body}");
  }

  void setLocalStorageValues() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString('user_id', '');
    prefs.setString('Email_ID', '');
    prefs.setString('User_name', '');
    prefs.setString('First_name', '');
    prefs.setString('Last_name', '');
    prefs.setString('Session_token', '');
    prefs.setDouble('Coins', 0.0);
    prefs.setString('DateTime', '');
  }

  Future getNewToken() async {
    final String? refreshTok =
        await PreferenceHelper.getPreferenceData(PreferenceHelper.refreshToken);
    final String? emailAddress =
        await PreferenceHelper.getPreferenceData(PreferenceHelper.email);

    log("GetNewToken====>>>>${AllHttpRequest.apiUrl}token/refresh");
    log("RefreshToken====>>>>$refreshTok");
    // set up POST request arguments
    String url = "${AllHttpRequest.apiUrl ?? ""}token/refresh";
    Map<String, String> headers = {
      "Accept": "application/json",
      "Content-Type": "application/json"
    };

    var body = {"refresh_token": "$refreshTok", "email": "$emailAddress"};

    var responseData = await http.post(Uri.parse(url),
        headers: headers, body: json.encode(body));
    log("${responseData.request!.headers}");
    log("${responseData.request}");
    log("${responseData.statusCode}");
    log('get Response body: ${responseData.body}');

    if (responseData.statusCode == 200) {
      log("HelloElsePart");
      // If the call to the server was successful, parse the JSON.
      var response = json.decode(responseData.body);

      PreferenceHelper.setPreferenceData(
          PreferenceHelper.accessToken, response["access_token"]);
      PreferenceHelper.setPreferenceData(
          PreferenceHelper.refreshToken, response["refresh_token"]);

      // AllHttpRequest allHttpRequest = AllHttpRequest();
      // allHttpRequest.getRequest(funName: funcName);
      return response;
    } else if (responseData.statusCode == 401) {
      CustomToast.showToastMessage(
          'Your session has been expired. Please login again.');

      /// clear the preference data
      PreferenceHelper.clearUserPreferenceData();

      // navigatorKey.currentState?.push();
      // NavigationService.instance.navigateToReplacement(LoginScreen.tag);'

      //Your session has been expired. Please login again.
    } else {
      return null;
    }
    // return {};
  }
}