import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
import 'package:haptic_feedback/haptic_feedback.dart';
import 'package:http/http.dart' as http;
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/nfc_manager_android.dart' show NfcAAndroid, NfcBAndroid;
import 'package:nfc_manager/nfc_manager_ios.dart' show MiFareIos, Iso15693Ios;
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/views/widgets/dialogs/confirm_dialog.dart';
import 'package:test_sa/views/widgets/dialogs/loading_with_text_dialog.dart';

// ignore_for_file: avoid_annotating_with_dynamic

class Utils {
  static bool _isLoadingVisible = false;

  static bool get isLoading => _isLoadingVisible;

  static void showToast(String message, {bool longDuration = true, ToastGravity toastGravity = ToastGravity.BOTTOM}) {
    Fluttertoast.showToast(
        msg: message,
        toastLength: longDuration ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT,
        gravity: toastGravity,
        timeInSecForIosWeb: 1,
        backgroundColor: Colors.black54,
        textColor: Colors.white,
        fontSize: 13.0);
  }

  static dynamic getNotNullValue(List<dynamic> list, int index) {
    try {
      return list[index];
    } catch (ex) {
      return null;
    }
  }

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

  static int stringToHex(String colorCode) {
    try {
      return int.parse(colorCode.replaceAll("#", "0xff"));
    } catch (ex) {
      return (0xff000000);
    }
  }

  static Future delay(int millis) async {
    return await Future.delayed(Duration(milliseconds: millis));
  }

  static void hapticFeedback() async {
    bool canVibrate = await Haptics.canVibrate();
    if (canVibrate) {
      Haptics.vibrate(HapticsType.heavy, useAndroidHapticConstants: Platform.isAndroid);
    }
  }

  static bool isBeforeOrEqualCurrentTime(TimeOfDay t1, TimeOfDay t2) {
    return t1.hour < t2.hour || (t1.hour == t2.hour && t1.minute <= t2.minute);
  }

  static void showLoading(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _isLoadingVisible = true;

      //  showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());

      showDialog(
        context: context,
        barrierColor: Colors.black.withOpacity(0.5),
        useRootNavigator: false,
        builder: (BuildContext context) => const AppLazyLoading(),
      ).then((value) {
        _isLoadingVisible = false;
      });
    });
  }

  static void hideLoading(BuildContext context) {
    if (_isLoadingVisible) {
      _isLoadingVisible = false;
      Navigator.of(context).pop();
    }
    _isLoadingVisible = false;
  }

  static void showLoadingWithTextDialog(BuildContext context, {String? message}) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _isLoadingVisible = true;

      showDialog(
        context: context,
        barrierColor: Colors.black.withOpacity(0.5),
        useRootNavigator: false,
        builder: (BuildContext context) => LoadingWithTextDialog(message: message),
      ).then((value) {
        _isLoadingVisible = false;
      });
    });
  }

  static Future<String> getStringFromPrefs(String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getString(key) ?? "";
  }

  static Future<bool> removeStringFromPrefs(String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.remove(key);
  }

  static Future<bool> saveStringFromPrefs(String key, String value) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return await prefs.setString(key, value);
  }

  // static void handleException(dynamic exception, cxt, Function(String)? onErrorMessage) {
  //   String errorMessage;
  //   if (exception.error.errorType != null && exception.error.errorType == 4) {
  //     Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.appUpdateScreen, (_) => false, arguments: exception.error?.errorMessage);
  //   } else {
  //     if (exception is APIException) {
  //       if (exception.message == APIException.UNAUTHORIZED) {
  //         return;
  //       } else {
  //         errorMessage = exception.error?.errorMessage ?? exception.message;
  //       }
  //     } else {
  //       errorMessage = APIException.UNKNOWN;
  //     }
  //     if (onErrorMessage != null) {
  //       onErrorMessage(errorMessage);
  //     } else {
  //       if (!AppState().isAuthenticated) {
  //         showDialog(
  //           barrierDismissible: false,
  //           context: cxt,
  //           builder: (cxt) => ConfirmDialog(
  //             message: errorMessage,
  //             onTap: () {
  //               Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route<dynamic> route) => false);
  //             },
  //             onCloseTap: () {},
  //           ),
  //         );
  //       } else {
  //         if (cxt != null) {
  //           confirmDialog(cxt, errorMessage);
  //         } else {
  //           showToast(errorMessage);
  //         }
  //       }
  //     }
  //   }
  // }
  //
  // static Future showErrorDialog({required BuildContext context, required VoidCallback onOkTapped, required String message}) async {
  //   return showDialog(
  //     context: context,
  //     builder: (BuildContext context) => ConfirmDialog(
  //       message: message,
  //       onTap: onOkTapped,
  //     ),
  //   );
  // }
  //
  static void confirmDialog(cxt, String message, {VoidCallback? onTap}) {
    showDialog(
      context: cxt,
      builder: (BuildContext cxt) => ConfirmDialog(
        message: message,
        onTap: onTap,
      ),
    );
  }

  static Future<File?> downloadFile(
    String url, {
    bool autoOpen = true,
    bool showToast = true,
    String? authToken,
    String? fileName,
  }) async {
    final client = http.Client();
    try {
      if (showToast) {
        Utils.showToast("Downloading file...", longDuration: false);
      }
      fileName ??= url.split('/').last.split('?').first;
      if (!fileName.contains('.')) {
        fileName = 'downloaded_file_${DateTime.now().millisecondsSinceEpoch}.jpg';
      }
      final request = http.Request('GET', Uri.parse(url));
      if (authToken != null) {
        request.headers['Authorization'] = 'Bearer $authToken';
      }
      request.followRedirects = false;
      final streamedResponse = await client.send(request);
      File? file;
      final dir = await getTemporaryDirectory();
      if (streamedResponse.statusCode == 302) {
        final redirectUrl = streamedResponse.headers['location'];
        if (redirectUrl == null) {
          throw Exception('302 Redirect missing Location header');
        }
        final headers = authToken != null ? {'Authorization': 'Bearer $authToken'} : <String, String>{};
        final fileResponse = await http.get(Uri.parse(redirectUrl), headers: headers);
        if (fileResponse.statusCode == 200) {
          file = File('${dir.path}/$fileName');
          await file.writeAsBytes(fileResponse.bodyBytes);
        } else {
          throw Exception('Download from redirect failed: ${fileResponse.statusCode}');
        }
      }
      else if (streamedResponse.statusCode == 200) {
        file = File('${dir.path}/$fileName');
        await file.writeAsBytes(await streamedResponse.stream.toBytes());
      }
      else {
        throw Exception('Download failed with status: ${streamedResponse.statusCode}');
      }
      if (showToast) {
        Utils.showToast("File downloaded successfully", longDuration: false);
      }
      if (autoOpen) {
        await OpenFile.open(file.path);
      }
      return file;
    } catch (ex) {
      if (showToast) {
        Utils.showToast("Download failed: ${ex.toString()}");
      }
      return null;
    } finally {
      client.close();
    }
  }

  static bool isLocalFile(String path) {
    if (path.isEmpty) return false;
    return path.startsWith("/") || path.startsWith("file://") || (path.length > 1 && path.substring(1).startsWith(':\\'));
  }

  //
  // static Widget getNoDataWidget(BuildContext context) {
  //   return Column(
  //     mainAxisAlignment: MainAxisAlignment.center,
  //     crossAxisAlignment: CrossAxisAlignment.center,
  //     children: [
  //       SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0),
  //       LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15),
  //     ],
  //   ).center;
  // }
  //
  // static Widget getNoChatWidget(BuildContext context) {
  //   return Column(
  //     mainAxisAlignment: MainAxisAlignment.center,
  //     crossAxisAlignment: CrossAxisAlignment.center,
  //     children: [
  //       SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0),
  //       LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15),
  //     ],
  //   ).center;
  // }
  //
  // static Uint8List getPostBytes(img) {
  //   try {
  //     var b64 = img.replaceFirst('data:image/png;base64,', '');
  //     if (img != null && Utils.isBase64(b64)) return Utils.dataFromBase64String(b64);
  //   } catch (e) {}
  //   return Uint8List.fromList([]);
  // }
  //
  // static String getBase64FromJpeg(img) {
  //   try {
  //     var b64 = img.replaceFirst('data:image/jpeg;base64,', '');
  //     return b64;
  //   } catch (e) {}
  //   return "";
  // }
  //
  // static bool isBase64(String str) {
  //   RegExp _base64 = RegExp(r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$');
  //   return _base64.hasMatch(str);
  // }
  //
  // static Uint8List dataFromBase64String(String base64String) {
  //   return base64Decode(base64String);
  // }
  //
  // static Widget tableColumnTitle(String? text, {bool showDivider = true, bool alignCenter = false}) {
  //   text ??= "";
  //   return Column(
  //     crossAxisAlignment: CrossAxisAlignment.start,
  //     mainAxisSize: MainAxisSize.min,
  //     children: [
  //       6.height,
  //       alignCenter ? text.toText12().center : text.toText12(),
  //       5.height,
  //       if (showDivider)
  //         const Divider(
  //           height: 1,
  //           color: Color(0xff2E303A),
  //           thickness: 1,
  //         )
  //     ],
  //   );
  // }
  //
  // static Decoration containerRadius(Color background, double radius) {
  //   return BoxDecoration(
  //     color: background,
  //     border: Border.all(
  //         width: 1, //
  //         color: background //                  <--- border width here
  //         ),
  //     borderRadius: BorderRadius.circular(radius),
  //   );
  // }
  //
  // static Widget mHeight(double h) {
  //   return Container(
  //     height: h,
  //   );
  // }
  //
  // static Widget mDivider(Color color) {
  //   return Divider(
  //     // width: double.infinity,
  //     height: 1,
  //     color: color,
  //   );
  // }
  //
  // static Widget tableColumnValue(String text, {bool isCapitable = true, bool alignCenter = false}) {
  //   return Column(
  //     crossAxisAlignment: CrossAxisAlignment.start,
  //     mainAxisSize: MainAxisSize.min,
  //     children: [
  //       12.height,
  //       if (alignCenter)
  //         (isCapitable ? text.toLowerCase().capitalizeFirstofEach : text).toText12(color: MyColors.normalTextColor).center
  //       else
  //         (isCapitable ? text.toLowerCase().capitalizeFirstofEach : text).toText12(color: MyColors.normalTextColor),
  //       12.height,
  //     ],
  //   );
  // }
  //
  // /// EIT Forms date formats
  //
  // static String getMonthNamedFormat(DateTime date) {
  //   /// it will return like "29-Sep-2022"
  //   return DateFormat('dd-MMM-yyyy', "en_US").format(date);
  // }
  //
  // static String reverseFormatDate(String date) {
  //   String formattedDate;
  //   if (date.isNotEmpty) {
  //     formattedDate = date.replaceAll('/', '-');
  //     formattedDate = formattedDate.replaceAll(' 00:00:00', '');
  //   } else {
  //     formattedDate = date;
  //   }
  //   return formattedDate;
  // }
  //
  // static String formatStandardDate(String date) {
  //   String formattedDate;
  //   if (date.isNotEmpty) {
  //     formattedDate = date.replaceAll('-', '/');
  //   } else {
  //     formattedDate = date;
  //   }
  //   return formattedDate;
  // }
  //
  // static String reverseFormatStandardDate(String date) {
  //   String formattedDate;
  //   if (date.isNotEmpty) {
  //     formattedDate = date.replaceAll('/', '-');
  //   } else {
  //     formattedDate = date;
  //   }
  //   return formattedDate;
  // }
  //
  // static String formatDate(String date) {
  //   String formattedDate;
  //
  //   if (date.isNotEmpty) {
  //     date = date.substring(0, 10);
  //     formattedDate = date.replaceAll('-', '/');
  //     formattedDate = formattedDate + ' 00:00:00';
  //   } else {
  //     formattedDate = date;
  //   }
  //   return formattedDate;
  // }
  //
  // static String formatDateNew(String date) {
  //   String formattedDate;
  //   if (date.isNotEmpty) {
  //     formattedDate = date.split('T')[0];
  //     if (!formattedDate.contains("00:00:00")) {
  //       formattedDate = formattedDate + ' 00:00:00';
  //     }
  //   } else {
  //     formattedDate = date;
  //   }
  //   return formattedDate;
  // }
  //
  // static String formatDateDefault(String date) {
  //   if (date.isNotEmpty) {
  //     if (date.toLowerCase().contains("t")) {
  //       date = date.toLowerCase().split("t")[0];
  //       if (!date.contains("00:00:00")) {
  //         date = date + ' 00:00:00';
  //       }
  //       return date;
  //     } else {
  //       if (date.toLowerCase().split("-")[1].length == 3) {
  //         return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('dd-MMM-yyyy', "en_US").parseLoose(date));
  //       } else {
  //         return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('yyyy-MM-dd', "en_US").parseLoose(date));
  //       }
  //       // return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
  //     }
  //   } else {
  //     return date;
  //   }
  // }
  //
  // static Future<DateTime> selectDate(BuildContext context, DateTime selectedDate) async {
  //   if (!Platform.isIOS) {
  //     await showCupertinoModalPopup(
  //       context: context,
  //       builder: (BuildContext cxt) => Container(
  //         height: 250,
  //         color: Colors.white,
  //         child: CupertinoDatePicker(
  //           backgroundColor: Colors.white,
  //           mode: CupertinoDatePickerMode.date,
  //           onDateTimeChanged: (DateTime value) {
  //             if (value != null && value != selectedDate) {
  //               selectedDate = value;
  //             }
  //           },
  //           initialDateTime: selectedDate,
  //         ),
  //       ),
  //     );
  //   } else {
  //     DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101));
  //     if (picked != null && picked != selectedDate) {
  //       selectedDate = picked;
  //     }
  //   }
  //   return selectedDate;
  // }

  static void readNFc({required Function(String) onRead}) async {
    // Stop any existing session before starting a new one
    try {
      await NfcManager.instance.stopSession();
    } catch (e) {
      print('No active session to stop: $e');
    }

    NfcManager.instance.startSession(
      onDiscovered: (NfcTag tag) async {
        String identifier = '';

        try {
          if (Platform.isAndroid) {
            // Try NfcA first (most common)
            final nfcA = NfcAAndroid.from(tag);
            if (nfcA != null) {
              identifier = nfcA.tag.id.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
            } else {
              // Fallback to NfcB
              final nfcB = NfcBAndroid.from(tag);
              if (nfcB != null) {
                identifier = nfcB.tag.id.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
              }
            }
          } else {
            // For iOS, try MiFare first
            final mifare = MiFareIos.from(tag);
            if (mifare != null) {
              identifier = mifare.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
            } else {
              // Fallback to Iso15693 for iOS
              final iso15693 = Iso15693Ios.from(tag);
              if (iso15693 != null) {
                identifier = iso15693.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
              }
            }
          }
        } catch (e) {
          print('Error reading NFC: $e');
        }

        try {
          await NfcManager.instance.stopSession();
        } catch (e) {
          print('Error stopping NFC session: $e');
        }
        onRead(identifier);
      },
      pollingOptions: {NfcPollingOption.iso14443},
    ).catchError((err) {
      print('NFC session error: $err');
      // Stop session on error
      NfcManager.instance.stopSession().catchError((e) {
        print('Error stopping session after error: $e');
      });
    });
  }

  //HUAWEI DECISION MAKING
  static Future<bool> isGoogleServicesAvailable() async {
    GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
    String status = availability.toString().split('.').last;
    if (status == "success") {
      return true;
    }
    return false;
  }
//
// static bool isDate(String input, String format) {
//   try {
//     DateTime d = DateFormat(format).parseStrict(input);
//     //print(d);
//     return true;
//   } catch (e) {
//     //print(e);
//     return false;
//   }
// }
}
