/* Created by Nitesh Kumar on 4/11/23 */
import 'dart:developer';

import 'package:encrypt/encrypt.dart';
import 'package:exide_crr/data/network_connectivity/network_info.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'dart:math' as math;


class Miscellaneous {
  static void logMessage(String className, Object? msg) {
    if (kDebugMode) {
      //print("$className : $msg");
      // developer.log("$msg", name: className);
      Get.log("$className : $msg");
    }
  }

  static void showToastMessage({required String message}) {
    Fluttertoast.cancel();
    Fluttertoast.showToast(msg: message);
  }

  static String suffixOrdinalToNum(int n) {
    if (n >= 11 && n <= 13) {
      return "th"; //th
    }
    switch (n % 10) {
      case 1:
        return "st"; //st
      case 2:
        return "nd"; //nd
      case 3:
        return "rd"; //rd
      default:
        return "th"; //th
    }
  }

  static String daysAgoString(String? from) {
    DateTime expDate = DateFormat('yyyy-MM-dd').parse(from!);

    int numberOfDays = ((DateTime.now().difference(expDate)).inDays);

    if (numberOfDays > 0) {
      return "Raised ${numberOfDays.abs()} days ago";
    } else if (numberOfDays == 0) {
      return "Raised today";
    } else {
      return "";
    }
  }

  static String getDateFormatInString(String? from) {
    if (from == null) {
      return '';
    }
    DateTime date = DateFormat('yyyy-MM-dd').parse(from);

    String textDate = DateFormat('dd MMM, yyyy').format(date);

    return textDate;
  }

  /// hex code into color
  static int? hexToColor({required String? colorStr}) {
    if (colorStr != null) {
      String formattedColorCode = colorStr.replaceAll("#", "");
      return int.parse(formattedColorCode, radix: 16) + 0xFF000000;
    } else {
      return null;
    }
  }

  static String getInitials(String user) {
    var buffer = StringBuffer();
    var initial = "";
    var split = user.split(RegExp(r'\s+'));
    for (var s in split) {
      if (s.isNotEmpty) {
        buffer.write(s[0]);
      }
    }

    initial = buffer.toString().substring(0, buffer.length).toUpperCase();
    if (initial.length > 3) {
      initial = initial.substring(0, 3);
    }
    return initial;
  }

  static String formatIndianRupee(
      {required double amount,
      bool isWithRupeeSymbol = true,
      bool isWithoutSuffix = false}) {
    var indiaFormat = NumberFormat.compactCurrency(
      locale: 'en_IN',
      symbol: isWithRupeeSymbol ? '₹' : '',
    );

    String formattedAmount = indiaFormat.format(amount).replaceAll("T", "K");
    if (isWithoutSuffix) {
      // Remove the suffix (K, L, Cr) if isWithoutSuffix is true
      formattedAmount = formattedAmount.replaceAll(RegExp('[A-Z]'), '');
    }

    return formattedAmount;
  }

  String formatIndianRupeeNoSymbol(double amount) {
    var indiaFormat = NumberFormat.compactCurrency(
      locale: 'en_IN',
      symbol: '',
    );
    return indiaFormat.format(amount);
  }

  static String formatNumberString(int? value) {
    if (value == null) return "";
    var formatter = NumberFormat(',###');
    return formatter.format(value);
  }

  String formatNumberType(int value, String unitType) {
    String formattedValue = value.toString();

    if (unitType == 'number') {
      // Add commas after every three digits
      final pattern = RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))');
      formattedValue =
          formattedValue.replaceAllMapped(pattern, (match) => '${match[1]},');
    } else if (unitType == 'percentage') {
      formattedValue = '$formattedValue%';
    } else if (unitType == 'lacs') {
      formattedValue = '₹$formattedValue L';
    } else if (unitType == 'thousand') {
      formattedValue = '₹$formattedValue K';
    }

    return formattedValue;
  }

  // Date Formatting : eg: 28 Mar, 23
  static String tableDateFormat(DateTime dateTime) {
    if (dateTime.isBefore(DateTime(1900, 01, 02))) {
      return "-";
    }
    return DateFormat("dd MMM ''yy").format(dateTime);
  }

  // convert double number into percentage string with % symbol at the end.
  static String doubleToPercentageString({required double value}) {
    final percentage = value.toStringAsFixed(2);
    // Check if the last two characters of the percentage string are "00"
    if (percentage.endsWith("00")) {
      // If they are, remove the % symbol from the end of the string
      return '${percentage.substring(0, percentage.length - 3)}%';
    } else {
      // If not, return the percentage string with the % symbol
      return '$percentage%';
    }
  }

  static void hideKeyboard(BuildContext? context) {
    if (context == null) return;
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
      FocusManager.instance.primaryFocus?.unfocus();
    }
  }

  static double getRangeValue(double max, double value) {
    double limit = (max * 2) / 100;
    if (value == 0) {
      return value;
    } else if (value < limit) {
      return limit;
    } else {
      return value;
    }
  }

  //To print the Firstname of Full name
  static String getFirstName(String? name) {
    if (name != null && name.isNotEmpty) {
      List<String> nameParts = name.split(' ');
      String firstName = nameParts[0];
      String capitalizedFirstName =
          firstName[0].toUpperCase() + firstName.substring(1);
      return capitalizedFirstName;
    } else {
      return '';
    }
  }

  static bool checkIsTarget({required int value}) {
    return value.toString() == '1';
  }

  static String capitalizeNameByWord(String? name,
      {bool replaceDotsWithSpaces = false}) {
    if (name == null || name.isEmpty) {
      return "";
    }

    if (replaceDotsWithSpaces) {
      // Replace dots with spaces
      name = name.replaceAll(".", " ");
    }

    List<String> words = (name.toLowerCase().trim())
        .split(' ')
        .where((str) => str.isNotEmpty)
        .toList();
    words = words.map((word) {
      if (word.length == 1) {
        return word.toUpperCase();
      } else {
        return word[0].toUpperCase() + word.substring(1);
      }
    }).toList();

    return words.join(' ');
  }

  static DateTime? convertStringToDate(String? dateString) {
    if (dateString == null || dateString.isEmpty) {
      return null;
    }

    try {
      return DateTime.parse(dateString);
    } catch (e) {
      log("Error parsing date: $e");
      return null;
    }
  }

  static String addIndianMobileNumberPrefixIfMissing(String phoneNumber) {
    const String indiaCountryCode = "+91 ";
    const int expectedPhoneNumberLength = 10;

    if (phoneNumber.isEmpty || phoneNumber == "0") {
      return "-";
    }

    if (phoneNumber.length == expectedPhoneNumberLength) {
      // Add the prefix if it's missing
      return indiaCountryCode + phoneNumber;
    } else if (phoneNumber.startsWith(indiaCountryCode) &&
        phoneNumber.length ==
            expectedPhoneNumberLength + indiaCountryCode.length) {
      // The number already has the correct prefix, so return as is
      return phoneNumber;
    } else {
      return phoneNumber;
    }
  }

  static int getKpiBucketNumber(num? percentileValue) {
    if (percentileValue == null) return 0;
    if (percentileValue >= 0 && percentileValue <= 20) {
      return 1;
    } else if (percentileValue >= 21 && percentileValue <= 40) {
      return 2;
    } else if (percentileValue >= 41 && percentileValue <= 60) {
      return 3;
    } else if (percentileValue >= 61 && percentileValue <= 80) {
      return 4;
    } else if (percentileValue >= 81 && percentileValue <= 100) {
      return 5;
    } else {
      return 0;
    }
  }

  static Future<bool> isNetworkConnected() async {
    final networkInfoController = Get.find<NetworkInfo>();
    if (!await networkInfoController.isConnected()) {
      return false;
    } else {
      return true;
    }
  }

  static String setEncryptData(
      {required String encryptingData, required String encryptionKey}) {
    final keyValue = encrypt.Key.fromUtf8(encryptionKey);
    final iv = encrypt.IV.fromLength(8); // Assuming AES-128
    final encryptor =
        encrypt.Encrypter(encrypt.AES(keyValue, mode: encrypt.AESMode.ecb));

    final encrypted = encryptor.encrypt(
        getSaltedData(data: encryptingData, encryptionKey: encryptionKey),
        iv: iv);
    Miscellaneous.logMessage("Miscellaneous",
        "encryptingData $encryptingData encrypted ${encrypted.base64}");
    return encrypted.base64;
  }

  static String getSaltedData(
      {required String data, required String encryptionKey}) {
    String encryptedData = "$data|$encryptionKey";
    return encryptedData;
  }

  static String getDecryptSecureData(
      {required String encryptedData, required String encryptionKey}) {
    final key = encrypt.Key.fromUtf8(encryptionKey);
    final iv = IV.fromLength(8); // Assuming AES-128
    final encryptor = Encrypter(AES(key, mode: AESMode.ecb));

    final encrypted = Encrypted.fromBase64(encryptedData);
    final decrypted = encryptor.decrypt(encrypted, iv: iv);

    return decrypted;
  }

//////////////// FOR BIP/ 1Up APIS only//////////////////////////

  static String? encryptData(
      {String? encryptedData, required String encryptionKey}) {
    if (encryptedData == null) {
      return null;
    }
    final encrypt.Key encryptKey = encrypt.Key.fromUtf8(encryptionKey);
    final iv = encrypt.IV.fromLength(16);
    final encrypted = encrypt.Encrypter(encrypt.AES(
      encryptKey,
      mode: encrypt.AESMode.ecb,
    ));
    return encrypted.encrypt(encryptedData, iv: iv).base64;
  }

  static String encryptBytesData(
      {required List<int> encryptedData, required String encryptionKey}) {
    final encrypt.Key encryptKey = encrypt.Key.fromUtf8(encryptionKey);
    final iv = encrypt.IV.fromLength(32);
    final encrypted =
        encrypt.Encrypter(encrypt.AES(encryptKey, mode: encrypt.AESMode.ecb));
    return encrypted.encryptBytes(encryptedData, iv: iv).base64;
  }

  static dynamic decryptData(
      {required String data, int? statusCode, required String encryptionKey}) {
    //updated by chandra ....This 200 condition was added because from apigee only 200 response is encrypted ...
    // Other response is sent RAW(as it is)
    if (statusCode == 200) {
      final encrypt.Key encryptKey = encrypt.Key.fromUtf8(encryptionKey);
      final iv = encrypt.IV.fromLength(32);
      final encrypted =
          encrypt.Encrypter(encrypt.AES(encryptKey, mode: encrypt.AESMode.ecb));
      return encrypted.decrypt64(data, iv: iv);
    } else {
      return data;
    }
  }

///////////////////////////////////////////////////////////////////////////

  static bool isPathValid(String path) {
    // If exactly matches root then it is fine.
    if (path.removeAllWhitespace == '/') return true;
    final List<GetPage<dynamic>> treeBranch =
        Get.routeTree.matchRoute(path).treeBranch;

    // Note: for some reason .where was not working on the .treeBranch iterable.
    final List<String> list = <String>[];
    for (final GetPage<dynamic> element in treeBranch) {
      // Need to exclude '/' as it is the root route so any uri beginning
      // with / will give a valid path
      if (element.name != '/') {
        list.add(element.name);
      }
    }
    return list.isNotEmpty;
  }

  static double getTrackYourPerformanceRotation(
      {required int value, required int target}) {
    double percentage = (value / target) * 100;
    if (percentage >= 100) {
      return 0;
    } else if (percentage >= 80 && percentage < 100) {
      return -math.pi / 1.0;
    } else {
      return -math.pi / 1.0;
    }
  }

  static bool isNumeric(String? str) {
    if (str == null) {
      return false;
    }
    return double.tryParse(str) != null;
  }

  static String generateOTP() {
    final math.Random random = math.Random();
    final int otp = 1000 + random.nextInt(9000); // Ensures a 4-digit number
    return otp.toString();
  }
}