import 'package:flutter/material.dart';
import '/backend/schema/enums/enums.dart';
import 'backend/api_requests/api_manager.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:csv/csv.dart';
import 'package:synchronized/synchronized.dart';
import 'flutterlib/flutter_util.dart';
import 'dart:convert';

class FFAppState extends ChangeNotifier {
  static FFAppState _instance = FFAppState._internal();

  factory FFAppState() {
    return _instance;
  }

  FFAppState._internal();

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

  Future initializePersistedState() async {
    secureStorage = FlutterSecureStorage();
    await _safeInitAsync(() async {
      _token = await secureStorage.getString('ff_token') ?? _token;
    });
    await _safeInitAsync(() async {
      _email = await secureStorage.getString('ff_email') ?? _email;
    });
    await _safeInitAsync(() async {
      _password = await secureStorage.getString('ff_password') ?? _password;
    });
    await _safeInitAsync(() async {
      _addPermissionsID =
          await secureStorage.getStringList('ff_addPermissionsID') ??
              _addPermissionsID;
    });
    await _safeInitAsync(() async {
      _removePermissionsID =
          await secureStorage.getStringList('ff_removePermissionsID') ??
              _removePermissionsID;
    });
  }

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

  late FlutterSecureStorage secureStorage;

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

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

  int _userid = 0;
  int get userid => _userid;
  set userid(int _value) {
    _userid = _value;
  }

  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 _password = '';
  String get password => _password;
  set password(String _value) {
    _password = _value;
    secureStorage.setString('ff_password', _value);
  }

  void deletePassword() {
    secureStorage.delete(key: 'ff_password');
  }

  bool _showChat = false;
  bool get showChat => _showChat;
  set showChat(bool _value) {
    _showChat = _value;
  }

  String _roleID = '';
  String get roleID => _roleID;
  set roleID(String _value) {
    _roleID = _value;
  }

  int _memberID = 0;
  int get memberID => _memberID;
  set memberID(int _value) {
    _memberID = _value;
  }

  List<String> _addPermissionsID = [];
  List<String> get addPermissionsID => _addPermissionsID;
  set addPermissionsID(List<String> _value) {
    _addPermissionsID = _value;
    secureStorage.setStringList('ff_addPermissionsID', _value);
  }

  void deleteAddPermissionsID() {
    secureStorage.delete(key: 'ff_addPermissionsID');
  }

  void addToAddPermissionsID(String _value) {
    _addPermissionsID.add(_value);
    secureStorage.setStringList('ff_addPermissionsID', _addPermissionsID);
  }

  void removeFromAddPermissionsID(String _value) {
    _addPermissionsID.remove(_value);
    secureStorage.setStringList('ff_addPermissionsID', _addPermissionsID);
  }

  void removeAtIndexFromAddPermissionsID(int _index) {
    _addPermissionsID.removeAt(_index);
    secureStorage.setStringList('ff_addPermissionsID', _addPermissionsID);
  }

  void updateAddPermissionsIDAtIndex(
    int _index,
    String Function(String) updateFn,
  ) {
    _addPermissionsID[_index] = updateFn(_addPermissionsID[_index]);
    secureStorage.setStringList('ff_addPermissionsID', _addPermissionsID);
  }

  void insertAtIndexInAddPermissionsID(int _index, String _value) {
    _addPermissionsID.insert(_index, _value);
    secureStorage.setStringList('ff_addPermissionsID', _addPermissionsID);
  }

  dynamic _docStatus = jsonDecode('{\"status\":\"completed\"}');
  dynamic get docStatus => _docStatus;
  set docStatus(dynamic _value) {
    _docStatus = _value;
  }

  List<String> _removePermissionsID = [];
  List<String> get removePermissionsID => _removePermissionsID;
  set removePermissionsID(List<String> _value) {
    _removePermissionsID = _value;
    secureStorage.setStringList('ff_removePermissionsID', _value);
  }

  void deleteRemovePermissionsID() {
    secureStorage.delete(key: 'ff_removePermissionsID');
  }

  void addToRemovePermissionsID(String _value) {
    _removePermissionsID.add(_value);
    secureStorage.setStringList('ff_removePermissionsID', _removePermissionsID);
  }

  void removeFromRemovePermissionsID(String _value) {
    _removePermissionsID.remove(_value);
    secureStorage.setStringList('ff_removePermissionsID', _removePermissionsID);
  }

  void removeAtIndexFromRemovePermissionsID(int _index) {
    _removePermissionsID.removeAt(_index);
    secureStorage.setStringList('ff_removePermissionsID', _removePermissionsID);
  }

  void updateRemovePermissionsIDAtIndex(
    int _index,
    String Function(String) updateFn,
  ) {
    _removePermissionsID[_index] = updateFn(_removePermissionsID[_index]);
    secureStorage.setStringList('ff_removePermissionsID', _removePermissionsID);
  }

  void insertAtIndexInRemovePermissionsID(int _index, String _value) {
    _removePermissionsID.insert(_index, _value);
    secureStorage.setStringList('ff_removePermissionsID', _removePermissionsID);
  }

  String _status = 'In progress';
  String get status => _status;
  set status(String _value) {
    _status = _value;
  }

  String _failed = 'Failed';
  String get failed => _failed;
  set failed(String _value) {
    _failed = _value;
  }
}

LatLng? _latLngFromString(String? val) {
  if (val == null) {
    return null;
  }
  final split = val.split(',');
  final lat = double.parse(split.first);
  final lng = double.parse(split.last);
  return LatLng(lat, lng);
}

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 CsvToListConverter()
            .convert(result)
            .first
            .map((e) => e.toString())
            .toList();
      });
  Future<void> setStringList(String key, List<String> value) async =>
      await writeSync(key: key, value: ListToCsvConverter().convert([value]));
}
