import 'dart:async';
import 'dart:convert';

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import '../models/token_model.dart';
import '../models/user_model.dart';

abstract class AuthLocalDataSource {
  Future<void> saveTokens(TokenModel tokens);
  Future<TokenModel?> getTokens();
  Future<void> deleteTokens();
  Future<void> saveUser(UserModel user);
  Future<UserModel?> getUser();
  Future<void> deleteUser();
  Future<void> clearAll();
  Stream<bool> get authStateChanges;
  void notifyAuthStateChanged(bool isAuthenticated);
}

class AuthLocalDataSourceImpl implements AuthLocalDataSource {
  final FlutterSecureStorage _storage;
  final _authStateController = StreamController<bool>.broadcast();

  static const String _accessTokenKey = 'access_token';
  static const String _refreshTokenKey = 'refresh_token';
  static const String _tokenTypeKey = 'token_type';
  static const String _userKey = 'current_user';

  AuthLocalDataSourceImpl({required FlutterSecureStorage storage})
      : _storage = storage;

  @override
  Future<void> saveTokens(TokenModel tokens) async {
    await Future.wait([
      _storage.write(key: _accessTokenKey, value: tokens.accessToken),
      _storage.write(key: _refreshTokenKey, value: tokens.refreshToken),
      _storage.write(key: _tokenTypeKey, value: tokens.tokenType),
    ]);
  }

  @override
  Future<TokenModel?> getTokens() async {
    final accessToken = await _storage.read(key: _accessTokenKey);
    final refreshToken = await _storage.read(key: _refreshTokenKey);
    final tokenType = await _storage.read(key: _tokenTypeKey);

    if (accessToken == null || refreshToken == null) {
      return null;
    }

    return TokenModel(
      accessToken: accessToken,
      refreshToken: refreshToken,
      tokenType: tokenType ?? 'bearer',
    );
  }

  @override
  Future<void> deleteTokens() async {
    await Future.wait([
      _storage.delete(key: _accessTokenKey),
      _storage.delete(key: _refreshTokenKey),
      _storage.delete(key: _tokenTypeKey),
    ]);
  }

  @override
  Future<void> saveUser(UserModel user) async {
    await _storage.write(key: _userKey, value: json.encode(user.toJson()));
  }

  @override
  Future<UserModel?> getUser() async {
    final userJson = await _storage.read(key: _userKey);
    if (userJson == null) {
      return null;
    }
    return UserModel.fromJson(json.decode(userJson));
  }

  @override
  Future<void> deleteUser() async {
    await _storage.delete(key: _userKey);
  }

  @override
  Future<void> clearAll() async {
    await Future.wait([
      deleteTokens(),
      deleteUser(),
    ]);
    notifyAuthStateChanged(false);
  }

  @override
  Stream<bool> get authStateChanges => _authStateController.stream;

  @override
  void notifyAuthStateChanged(bool isAuthenticated) {
    _authStateController.add(isAuthenticated);
  }
}
