// import 'dart:ffi';

import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:csv/csv.dart';
import 'package:local_auth/local_auth.dart';
import 'package:synchronized/synchronized.dart';

class FFAppState extends ChangeNotifier {
  // Adiciona a variável para controle de autenticação biométrica
  bool _isBiometricAuthenticated = false;
  bool get isBiometricAuthenticated => _isBiometricAuthenticated;

  // Instância do LocalAuthentication
  final LocalAuthentication auth = LocalAuthentication();

  // Verifica suporte biométrico
  Future<bool> checkBiometrics() async {
    try {
      return await auth.canCheckBiometrics;
    } catch (e) {
      clearBiometricAuthentication();
      debugPrint('Error checking biometrics: $e');
      return false;
    }
  }

  // Solicita autenticação biométrica
  Future<void> authenticateBiometric() async {
    bool authenticated = false;
    try {
      authenticated = await auth.authenticate(
          localizedReason: 'Scan your fingerprint to authenticate',
          options: const AuthenticationOptions(
            biometricOnly: true,
            stickyAuth: true,
            useErrorDialogs: true,
            sensitiveTransaction: true,
          ));
      if (authenticated) {
        _isBiometricAuthenticated = true;
        notifyListeners();
        return Future.value();
        // Salvar o estado de autenticação biométrica, se necessário
      }
    } catch (e) {
      print(e);
      debugPrint('Error authenticating: $e');
      clearBiometricAuthentication();
      return Future.error(e);
    }
    return Future.error(
        ''); // Add this line to ensure a value is always returned
  }

  // Função para limpar o estado de autenticação biométrica
  void clearBiometricAuthentication() {
    _isBiometricAuthenticated = false;
    notifyListeners();
    // Limpar a informação salva, se necessário
  }

  static FFAppState _instance = FFAppState._internal();

  factory FFAppState() {
    return _instance;
  }

  FFAppState._internal();

  static void reset() {
    _instance = FFAppState._internal();
  }

  Future initializePersistedState() async {
    secureStorage = const FlutterSecureStorage();
    await _safeInitAsync(() async {
      _cliUUID = await secureStorage.getString('ff_cliUUID') ?? _cliUUID;
    });
    await _safeInitAsync(() async {
      _ownerUUID = await secureStorage.getString('ff_ownerUUID') ?? _ownerUUID;
    });
    await _safeInitAsync(() async {
      _userUUID = await secureStorage.getString('ff_userUUID') ?? _userUUID;
    });
    await _safeInitAsync(() async {
      _devUUID = await secureStorage.getString('ff_devUUID') ?? _devUUID;
    });
    await _safeInitAsync(() async {
      _email = await secureStorage.getString('ff_email') ?? _email;
    });
    await _safeInitAsync(() async {
      _passwd = await secureStorage.getString('ff_passwd') ?? _passwd;
    });
    await _safeInitAsync(() async {
      _device = await secureStorage.getString('ff_device') ?? _device;
    });
    await _safeInitAsync(() async {
      _isLogged = await secureStorage.getBool('ff_isLogged') ?? _isLogged;
    });
    await _safeInitAsync(() async {
      _local = await secureStorage.getString('ff_local') ?? _local;
    });
    await _safeInitAsync(() async {
      _token = await secureStorage.getString('ff_token') ?? _token;
    });
    await _safeInitAsync(() async {
      _createdAt = await secureStorage.getString('ff_createdAt') ?? _createdAt;
    });
    await _safeInitAsync(() async {
      _updatedAt = await secureStorage.getString('ff_updatedAt') ?? _updatedAt;
    });
    await _safeInitAsync(() async {
      _status = await secureStorage.getString('ff_status') ?? _status;
    });
    await _safeInitAsync(() async {
      _name = await secureStorage.getString('ff_name') ?? _name;
    });
    await _safeInitAsync(() async {
      _tokenAPNS = await secureStorage.getString('ff_tokenAPNS') ?? _tokenAPNS;
    });
    await _safeInitAsync(() async {
      _userDevUUID =
          await secureStorage.getString('ff_user_dev_id') ?? _userDevUUID;
    });
    await _safeInitAsync(() async {
      _serialNumber =
          await secureStorage.getString('ff_serialNumber') ?? _serialNumber;
    });
    await _safeInitAsync(() async {
      _fingerprintOPT =
          await secureStorage.getBool('fingerprint') ?? _fingerprintOPT;
    });
    await _safeInitAsync(() async {
      _personOPT = await secureStorage.getBool('person') ?? _personOPT;
    });
    await _safeInitAsync(() async {
      _passOPT = await secureStorage.getBool('pass') ?? _passOPT;
    });
    await _safeInitAsync(() async {
      _panicOPT = await secureStorage.getBool('panic') ?? _panicOPT;
    });
    await _safeInitAsync(() async {
      _notifyOPT = await secureStorage.getBool('notify') ?? _notifyOPT;
    });
    await _safeInitAsync(() async {
      _accessPass = await secureStorage.getString('accessPass') ?? _accessPass;
    });
    await _safeInitAsync(() async {
      _panicPass = await secureStorage.getString('panicPass') ?? _panicPass;
    });
    await _safeInitAsync(() async {
      _fingerprintPass =
          await secureStorage.getString('fingerprintPass') ?? _fingerprintPass;
    });
  }

  void update(VoidCallback callback) {
    callback();
    notifyListeners();
  }

  late FlutterSecureStorage secureStorage;

  bool _panicOPT = false;
  bool get panic => _panicOPT;
  set panic(bool value) {
    _panicOPT = value;
    secureStorage.setBool('panic', value);
  }

  void deletePanic() {
    secureStorage.delete(key: 'panic');
  }

  String _fingerprintPass = '';
  String get fingerprintPass => _fingerprintPass;
  set fingerprintPass(String value) {
    _fingerprintPass = value;
    secureStorage.setString('fingerprintPass', value);
  }

  void deleteFingerprintPass() {
    secureStorage.delete(key: 'fingerprintPass');
  }

  String _accessPass = '';
  String get accessPass => _accessPass;
  set accessPass(String value) {
    _accessPass = value;
    secureStorage.setString('accessPass', value);
  }

  void deleteAccessPass() {
    secureStorage.delete(key: 'accessPass');
  }

  String _panicPass = '';
  String get panicPass => _panicPass;
  set panicPass(String value) {
    _panicPass = value;
    secureStorage.setString('panicPass', value);
  }

  void deletePanicPass() {
    secureStorage.delete(key: 'panicPass');
  }

  bool _notifyOPT = false;
  bool get notify => _notifyOPT;
  set notify(bool value) {
    _notifyOPT = value;
    secureStorage.setBool('notify', value);
  }

  bool _passOPT = false;
  bool get pass => _passOPT;
  set pass(bool value) {
    _passOPT = value;
    secureStorage.setBool('pass', value);
  }

  void deletePass() {
    secureStorage.delete(key: 'pass');
  }

  bool _personOPT = false;
  bool get person => _personOPT;
  set person(bool value) {
    _personOPT = value;
    secureStorage.setBool('person', value);
  }

  void deletePerson() {
    secureStorage.delete(key: 'person');
  }

  bool _fingerprintOPT = false;
  bool get fingerprint => _fingerprintOPT;
  set fingerprint(bool value) {
    _fingerprintOPT = value;
    secureStorage.setBool('fingerprint', value);
  }

  void deleteFingerprint() {
    secureStorage.delete(key: 'fingerprint');
  }

  String _serialNumber = '';
  String get serialNumber => _serialNumber;
  set serialNumber(String value) {
    _serialNumber = value;
    secureStorage.setString('ff_serialNumber', value);
  }

  void deleteSerialNumber() {
    secureStorage.delete(key: 'ff_serialNumber');
  }

  String _cliUUID = '';
  String get cliUUID => _cliUUID;
  set cliUUID(String value) {
    _cliUUID = value;
    secureStorage.setString('ff_cliUUID', value);
  }

  void deleteCliUUID() {
    secureStorage.delete(key: 'ff_cliUUID');
  }

  String _userDevUUID = '';
  String get userDevUUID => _userDevUUID;
  set userDevUUID(String value) {
    _userDevUUID = value;
    secureStorage.setString('ff_user_dev_id', value);
  }

  void deleteRemoteId() {
    secureStorage.delete(key: 'ff_user_dev_id');
  }

  String? _tokenAPNS = '';
  String? get tokenAPNS => _tokenAPNS;

  set tokenAPNS(String? value) {
    _tokenAPNS = value;
    // Verifica se o valor é nulo antes de tentar salvar no secureStorage
    if (value != null) {
      secureStorage.setString('ff_tokenAPNS', value);
    } else {
      secureStorage.delete(key: 'ff_tokenAPNS');
    }
  }

  void deleteTokenAPNS() {
    secureStorage.delete(key: 'ff_tokenAPNS');
  }

  String _ownerUUID = '';
  String get ownerUUID => _ownerUUID;
  set ownerUUID(String value) {
    _ownerUUID = value;
    secureStorage.setString('ff_ownerUUID', value);
  }

  void deleteOwnerUUID() {
    secureStorage.delete(key: 'ff_ownerUUID');
  }

  String _userUUID = '';
  String get userUUID => _userUUID;
  set userUUID(String value) {
    _userUUID = value;
    secureStorage.setString('ff_userUUID', value);
  }

  void deleteUserUUID() {
    secureStorage.delete(key: 'ff_userUUID');
  }

  String _devUUID = '';
  String get devUUID => _devUUID;
  set devUUID(String value) {
    _devUUID = value;
    secureStorage.setString('ff_devUUID', value);
  }

  void deleteDevUUID() {
    secureStorage.delete(key: 'ff_devUUID');
  }

  String _email = '';
  String get email => _email;
  set email(String value) {
    _email = value;
    secureStorage.setString('ff_email', value);
  }

  void deleteEmail() {
    secureStorage.delete(key: 'ff_email');
  }

  String _passwd = '';
  String get passwd => _passwd;
  set passwd(String value) {
    _passwd = value;
    secureStorage.setString('ff_passwd', value);
  }

  void deletePasswd() {
    secureStorage.delete(key: 'ff_passwd');
  }

  String _device = '';
  String get device => _device;
  set device(String value) {
    _device = value;
    secureStorage.setString('ff_device', value);
  }

  void deleteDevice() {
    secureStorage.delete(key: 'ff_device');
  }

  bool _isLogged = false;
  bool get isLogged => _isLogged;
  set isLogged(bool value) {
    _isLogged = value;
    secureStorage.setBool('ff_isLogged', value);
  }

  void deleteIsLogged() {
    secureStorage.delete(key: 'ff_isLogged');
  }

  String _local = '';
  String get local => _local;
  set local(String value) {
    _local = value;
    secureStorage.setString('ff_local', value);
  }

  void deleteLocal() {
    secureStorage.delete(key: 'ff_local');
  }

  String _token = '';
  String get token => _token;
  set token(String value) {
    _token = value;
    secureStorage.setString('ff_token', value);
  }

  void deleteToken() {
    secureStorage.delete(key: 'ff_token');
  }

  String _createdAt = '';
  String get createdAt => _createdAt;
  set createdAt(String value) {
    _createdAt = value;
    secureStorage.setString('ff_createdAt', value);
  }

  void deleteCreatedAt() {
    secureStorage.delete(key: 'ff_createdAt');
  }

  String _updatedAt = '';
  String get updatedAt => _updatedAt;
  set updatedAt(String value) {
    _updatedAt = value;
    secureStorage.setString('ff_updatedAt', value);
  }

  void deleteUpdatedAt() {
    secureStorage.delete(key: 'ff_updatedAt');
  }

  String _status = '';
  String get status => _status;
  set status(String value) {
    _status = value;
    secureStorage.setString('ff_status', value);
  }

  void deleteStatus() {
    secureStorage.delete(key: 'ff_status');
  }

  String _name = '';
  String get name => _name;
  set name(String value) {
    _name = value;
    secureStorage.setString('ff_name', value);
  }

  void deleteName() {
    secureStorage.delete(key: 'ff_name');
  }

  void deleteAll() {
    secureStorage.deleteAll();
  }
}

void _safeInit(Function() initializeField) {
  try {
    initializeField();
  } catch (_) {}
}

Future _safeInitAsync(Function() initializeField) async {
  try {
    await initializeField();
  } catch (_) {}
}

extension FlutterSecureStorageExtensions on FlutterSecureStorage {
  static final _lock = Lock();

  Future<void> writeSync({required String key, String? value}) async =>
      await _lock.synchronized(() async {
        await write(key: key, value: value);
      });

  void remove(String key) => delete(key: key);

  Future<String?> getString(String key) async => await read(key: key);
  Future<void> setString(String key, String value) async =>
      await writeSync(key: key, value: value);

  Future<bool?> getBool(String key) async => (await read(key: key)) == 'true';
  Future<void> setBool(String key, bool value) async =>
      await writeSync(key: key, value: value.toString());

  Future<int?> getInt(String key) async =>
      int.tryParse(await read(key: key) ?? '');
  Future<void> setInt(String key, int value) async =>
      await writeSync(key: key, value: value.toString());

  Future<double?> getDouble(String key) async =>
      double.tryParse(await read(key: key) ?? '');
  Future<void> setDouble(String key, double value) async =>
      await writeSync(key: key, value: value.toString());

  Future<List<String>?> getStringList(String key) async =>
      await read(key: key).then((result) {
        if (result == null || result.isEmpty) {
          return null;
        }
        return const CsvToListConverter()
            .convert(result)
            .first
            .map((e) => e.toString())
            .toList();
      });
  Future<void> setStringList(String key, List<String> value) async =>
      await writeSync(
          key: key, value: const ListToCsvConverter().convert([value]));
}
