import 'dart:convert';

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../../../../core/constants/api_constants.dart';
import '../../../../core/errors/exceptions.dart';
import '../models/user_model.dart';

abstract class AuthLocalDataSource {
  Future<UserModel?> getCachedUser();
  Future<void> cacheUser(UserModel user);
  Future<void> clearUserData();
  Future<void> saveTokens({
    required String accessToken,
    required String refreshToken,
    required String sessionId,
    required String csrfToken,
  });
  Future<String?> getAccessToken();
  Future<String?> getRefreshToken();
  Future<String?> getSessionId();
  Future<String?> getCsrfToken();
  Future<void> clearTokens();
  Future<bool> hasValidTokens();
}

class AuthLocalDataSourceImpl implements AuthLocalDataSource {
  final SharedPreferences sharedPreferences;
  final FlutterSecureStorage secureStorage;

  AuthLocalDataSourceImpl({
    required this.sharedPreferences,
    required this.secureStorage,
  });

  @override
  Future<UserModel?> getCachedUser() async {
    print('🔵 AUTH_LOCAL_DS: Getting cached user');
    
    try {
      final userJson = sharedPreferences.getString(AppConstants.userDataKey);
      print('🔵 AUTH_LOCAL_DS: User JSON from storage: $userJson');
      
      if (userJson != null) {
        final userMap = json.decode(userJson) as Map<String, dynamic>;
        print('🔵 AUTH_LOCAL_DS: Decoded user map: $userMap');
        final user = UserModel.fromJson(userMap);
        print('🟢 AUTH_LOCAL_DS: Successfully retrieved cached user: ${user.email}');
        return user;
      }
      
      print('🔵 AUTH_LOCAL_DS: No cached user found');
      return null;
    } catch (e) {
      print('🔴 AUTH_LOCAL_DS: Error getting cached user: $e');
      throw CacheException('Failed to get cached user');
    }
  }

  @override
  Future<void> cacheUser(UserModel user) async {
    print('🔵 AUTH_LOCAL_DS: Caching user: ${user.email}');
    
    try {
      final userJson = json.encode(user.toJson());
      print('🔵 AUTH_LOCAL_DS: User JSON to cache: $userJson');
      
      await sharedPreferences.setString(AppConstants.userDataKey, userJson);
      print('🟢 AUTH_LOCAL_DS: User cached successfully');
    } catch (e) {
      print('🔴 AUTH_LOCAL_DS: Error caching user: $e');
      throw CacheException('Failed to cache user');
    }
  }

  @override
  Future<void> clearUserData() async {
    try {
      await sharedPreferences.remove(AppConstants.userDataKey);
    } catch (e) {
      throw CacheException('Failed to clear user data');
    }
  }

  @override
  Future<void> saveTokens({
    required String accessToken,
    required String refreshToken,
    required String sessionId,
    required String csrfToken,
  }) async {
    print('🔵 AUTH_LOCAL_DS: Saving tokens');
    print('🔵 AUTH_LOCAL_DS: AccessToken length: ${accessToken.length}');
    print('🔵 AUTH_LOCAL_DS: RefreshToken length: ${refreshToken.length}');
    print('🔵 AUTH_LOCAL_DS: SessionId: $sessionId');
    print('🔵 AUTH_LOCAL_DS: CsrfToken length: ${csrfToken.length}');
    
    try {
      await Future.wait([
        secureStorage.write(key: AppConstants.accessTokenKey, value: accessToken),
        secureStorage.write(key: AppConstants.refreshTokenKey, value: refreshToken),
        secureStorage.write(key: AppConstants.sessionIdKey, value: sessionId),
        secureStorage.write(key: AppConstants.csrfTokenKey, value: csrfToken),
      ]);
      print('🟢 AUTH_LOCAL_DS: All tokens saved successfully');
    } catch (e) {
      print('🔴 AUTH_LOCAL_DS: Error saving tokens: $e');
      throw CacheException('Failed to save tokens');
    }
  }

  @override
  Future<String?> getAccessToken() async {
    try {
      return await secureStorage.read(key: AppConstants.accessTokenKey);
    } catch (e) {
      throw CacheException('Failed to get access token');
    }
  }

  @override
  Future<String?> getRefreshToken() async {
    try {
      return await secureStorage.read(key: AppConstants.refreshTokenKey);
    } catch (e) {
      throw CacheException('Failed to get refresh token');
    }
  }

  @override
  Future<String?> getSessionId() async {
    try {
      return await secureStorage.read(key: AppConstants.sessionIdKey);
    } catch (e) {
      throw CacheException('Failed to get session ID');
    }
  }

  @override
  Future<String?> getCsrfToken() async {
    try {
      return await secureStorage.read(key: AppConstants.csrfTokenKey);
    } catch (e) {
      throw CacheException('Failed to get CSRF token');
    }
  }

  @override
  Future<void> clearTokens() async {
    try {
      await Future.wait([
        secureStorage.delete(key: AppConstants.accessTokenKey),
        secureStorage.delete(key: AppConstants.refreshTokenKey),
        secureStorage.delete(key: AppConstants.sessionIdKey),
        secureStorage.delete(key: AppConstants.csrfTokenKey),
      ]);
    } catch (e) {
      throw CacheException('Failed to clear tokens');
    }
  }

  @override
  Future<bool> hasValidTokens() async {
    print('🔵 AUTH_LOCAL_DS: Checking for valid tokens');
    
    try {
      final accessToken = await getAccessToken();
      final sessionId = await getSessionId();
      
      print('🔵 AUTH_LOCAL_DS: AccessToken exists: ${accessToken != null}');
      print('🔵 AUTH_LOCAL_DS: SessionId exists: ${sessionId != null}');
      
      final hasTokens = accessToken != null && sessionId != null;
      print('🔵 AUTH_LOCAL_DS: Has valid tokens: $hasTokens');
      
      return hasTokens;
    } catch (e) {
      print('🔴 AUTH_LOCAL_DS: Error checking tokens: $e');
      return false;
    }
  }
} 