import 'dart:convert';

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import '../about/external/data/Commitment.dart';
import '../about/external/data/Program.dart';
import '../about/external/data/ResponseState.dart';
import '../about/external/data/SystemResponse.dart';
import '../about/internal/application/CapacityProfile.dart';
import '../about/internal/application/MeDescription.dart';
import '../about/internal/application/Token.dart';
import '../about/internal/application/UserDetails.dart';
import 'ConnectInternalMemory.dart';

/// Secure local storage. Keys carry a random suffix so they are not guessable
/// from the field name alone.
class InternalMemory implements ConnectInternalMemory {
  static const String DESCRIBE_ME = "DESCRIBE_ME_Kq7fRp2XvN4mLd8T";

  static const String NOT_TOKEN = "NOT_TOKEN_Zw3hYb9CsK6nQe1V";

  static const String USER_DETAILS_NEW = "USER_DETAILS_NEW_Rt5jXm8PfA2wDc7L";

  static const String ABOUT_ME = "ABOUT_ME_Hn4vTq7BdS9xGk3M";

  static const String TOKEN_DETAILS = "TOKEN_DETAILS_Ly6pWc3NrE8zFj5Q";

  static const String REFRESHER_ID = "REFRESHER_ID_Vb2sJd7MtX4qHu9K";

  static const String ACTIVE_COMMITMENT =
      "ACTIVE_COMMITMENT_Pf9kRn3WgY6tBz2S";

  static const String ACTIVE_PROGRAM = "ACTIVE_PROGRAM_Dm5cQx8LvH1rTk4N";

  static const String CAPACITY_PROFILE = "CAPACITY_PROFILE_Gs7bZp4JnW9dFy6X";

  static const String DEBT_SCORE = "DEBT_SCORE_Ux3mKt6QcR8vNa5H";

  static const String ENGAGEMENT_COUNT = "ENGAGEMENT_COUNT_Ct8nDw2FbP5jSq7Z";

  static const String AMNESTY_SPENT = "AMNESTY_SPENT_Jr4xVh9KmT3gLc6B";

  static const String SHOW_ONBOARDING = "SHOW_ONBOARDING_Nz6qGf2SdX7wPb4M";

  final groundedStorage = const FlutterSecureStorage();

  @override
  Future<MeDescription> getMyDescription() async {
    String? value = await groundedStorage.read(key: DESCRIBE_ME);

    if (value != null) {
      if (value != "") {
        Map<String, dynamic> json = jsonDecode(value);
        return MeDescription.fromJson(json);
      }
    }

    return MeDescription(id: "", name: "", token: "");
  }

  @override
  Future setMyDescription(MeDescription description) async {
    String value = jsonEncode(description.toJson());
    await groundedStorage.write(key: DESCRIBE_ME, value: value);
  }

  @override
  Future<String> getNotToken() async {
    return await groundedStorage.read(key: NOT_TOKEN) ?? "";
  }

  @override
  Future setNotToken(String token) async {
    await groundedStorage.write(key: NOT_TOKEN, value: token);
  }

  @override
  Future<SystemResponse> getUserCreationDetails() async {
    String? value = await groundedStorage.read(key: USER_DETAILS_NEW);

    if (value != null) {
      if (value != "") {
        Map<String, dynamic> json = jsonDecode(value);
        return SystemResponse.fromJsonMap(json);
      }
    }

    return SystemResponse("", "", "", ResponseState.Success);
  }

  @override
  Future setUserCreationDetails(SystemResponse response) async {
    String value = jsonEncode(response.toJson());
    await groundedStorage.write(key: USER_DETAILS_NEW, value: value);
  }

  @override
  Future<UserDetails> getUserDetails() async {
    String? value = await groundedStorage.read(key: ABOUT_ME);

    if (value != null) {
      if (value != "") {
        Map<String, dynamic> json = jsonDecode(value);
        return UserDetails.fromJson(json);
      }
    }

    return UserDetails(pic: '', name: '');
  }

  @override
  Future setUserDetails(UserDetails details) async {
    String value = jsonEncode(details.toJson());
    await groundedStorage.write(key: ABOUT_ME, value: value);
  }

  @override
  Future<Token> getTokenEntry() async {
    String? value = await groundedStorage.read(key: TOKEN_DETAILS);

    if (value != null) {
      if (value != "") {
        Map<String, dynamic> json = jsonDecode(value);
        return Token.fromJsonMap(json);
      }
    }

    return Token("", "", "", 0, "");
  }

  @override
  Future setTokenEntry(Token token) async {
    String value = jsonEncode(token.toJson());
    await groundedStorage.write(key: TOKEN_DETAILS, value: value);
  }

  @override
  Future<String> getRefreshAt() async {
    return await groundedStorage.read(key: REFRESHER_ID) ?? "";
  }

  @override
  Future setRefreshAt(String refresher) async {
    await groundedStorage.write(key: REFRESHER_ID, value: refresher);
  }

  @override
  Future<Commitment> getActiveCommitment() async {
    String? value = await groundedStorage.read(key: ACTIVE_COMMITMENT);

    if (value != null) {
      if (value.isNotEmpty) {
        Map<String, dynamic> json = jsonDecode(value);
        return Commitment.fromJson(json);
      }
    }

    return Commitment();
  }

  @override
  Future setActiveCommitment(Commitment commitment) async {
    String value = jsonEncode(commitment.toJson());
    await groundedStorage.write(key: ACTIVE_COMMITMENT, value: value);
  }

  @override
  Future<Program> getActiveProgram() async {
    String? value = await groundedStorage.read(key: ACTIVE_PROGRAM);

    if (value != null) {
      if (value.isNotEmpty) {
        Map<String, dynamic> json = jsonDecode(value);
        return Program.fromJson(json);
      }
    }

    return Program();
  }

  @override
  Future setActiveProgram(Program program) async {
    String value = jsonEncode(program.toJson());
    await groundedStorage.write(key: ACTIVE_PROGRAM, value: value);
  }

  @override
  Future<CapacityProfile> getCapacityProfile() async {
    String? value = await groundedStorage.read(key: CAPACITY_PROFILE);

    if (value != null) {
      if (value.isNotEmpty) {
        Map<String, dynamic> json = jsonDecode(value);
        return CapacityProfile.fromJson(json);
      }
    }

    return CapacityProfile();
  }

  @override
  Future setCapacityProfile(CapacityProfile profile) async {
    String value = jsonEncode(profile.toJson());
    await groundedStorage.write(key: CAPACITY_PROFILE, value: value);
  }

  @override
  Future<double> getCachedDebtScore() async {
    String? value = await groundedStorage.read(key: DEBT_SCORE);

    if (value != null) {
      return double.tryParse(value) ?? 0;
    }

    return 0;
  }

  @override
  Future setCachedDebtScore(double score) async {
    await groundedStorage.write(key: DEBT_SCORE, value: score.toString());
  }

  @override
  Future<int> getEngagementCount() async {
    String? value = await groundedStorage.read(key: ENGAGEMENT_COUNT);

    if (value != null) {
      return int.tryParse(value) ?? 0;
    }

    return 0;
  }

  @override
  Future setEngagementCount(int count) async {
    await groundedStorage.write(key: ENGAGEMENT_COUNT, value: count.toString());
  }

  @override
  Future<int> getAmnestySpent() async {
    String? value = await groundedStorage.read(key: AMNESTY_SPENT);

    if (value != null) {
      return int.tryParse(value) ?? 0;
    }

    return 0;
  }

  @override
  Future setAmnestySpent(int spent) async {
    await groundedStorage.write(key: AMNESTY_SPENT, value: spent.toString());
  }

  @override
  Future<bool> showOnboarding() async {
    String? value = await groundedStorage.read(key: SHOW_ONBOARDING);

    if (value != null) {
      return value.toLowerCase() == 'true';
    }

    return true;
  }

  @override
  Future setOnboardingOption(bool value) async {
    await groundedStorage.write(key: SHOW_ONBOARDING, value: value.toString());
  }
}
