import 'dart:convert';

import 'package:logging/logging.dart';

import 'package:pshared/api/errors/unauthorized.dart';
import 'package:pshared/api/responses/token.dart';
import 'package:pshared/config/constants.dart';
import 'package:pshared/service/secure_storage.dart';


class AuthorizationStorage {
  static final _logger = Logger('service.authorization.storage');

  static Future<TokenData> _getTokenData(String tokenKey) async {
    _logger.fine('Getting token data');
    final String? tokenJson = await SecureStorageService.get(tokenKey);
    if (tokenJson == null || tokenJson.isEmpty) {
      throw ErrorUnauthorized();
    }
    return TokenData.fromJson(jsonDecode(tokenJson));
  }


  static Future<bool> _checkTokenUsable(String keyName) async {
    final hasKey = await SecureStorageService.containsKey(keyName);
    if (!hasKey) return false;

    try {
      final tokenData = await _getTokenData(keyName);
      return tokenData.expiration.isAfter(DateTime.now());
    } catch (e, st) {
      _logger.warning('Error reading token from $keyName: $e', e, st);
      rethrow;
    }
  }


  static Future<bool> isAuthorizationStored() async {
    _logger.fine('Checking if authorization is stored');

    final accessUsable = await _checkTokenUsable(Constants.accessTokenStorageKey);
    if (accessUsable) return true;

    final refreshUsable = await _checkTokenUsable(Constants.refreshTokenStorageKey);
    if (refreshUsable) return true;

    return false;
  }


  static Future<TokenData> getAccessToken() async {
    _logger.fine('Getting access token');
    return _getTokenData(Constants.accessTokenStorageKey);
  }

  static Future<TokenData> getRefreshToken() async {
    _logger.fine('Getting refresh token');
    return _getTokenData(Constants.refreshTokenStorageKey);
  }

  static Future<void> updateToken(TokenData tokenData) async {
    _logger.fine('Storing access token...');
    final tokenJson = jsonEncode(tokenData.toJson());
    await SecureStorageService.set(Constants.accessTokenStorageKey, tokenJson);
  }

  static Future<void> updateRefreshToken(TokenData tokenData) async {
    _logger.fine('Storing refresh token...');
    final refreshTokenJson = jsonEncode(tokenData.toJson());
    await SecureStorageService.set(Constants.refreshTokenStorageKey, refreshTokenJson);
  }

  static Future<void> removeTokens() {
    return Future.wait([
      SecureStorageService.delete(Constants.refreshTokenStorageKey),
      SecureStorageService.delete(Constants.accessTokenStorageKey),
    ]);
  }
}


