// packages/service_api/lib/services/identity_service.dart

import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:uuid/uuid.dart';

class UserSession {
  final String userId;
  final String? userName;
  final String loginProvider;
  final String? email;

  UserSession({
    required this.userId,
    this.userName,
    this.loginProvider = "guest",
    this.email,
  });

  bool get isGuest => loginProvider == "guest";
}

class IdentityService {
  static const String _userIdKey = 'app_user_id';
  static const String _userNameKey = 'app_user_name';
  static const String _loginProviderKey = 'app_login_provider';
  static const String _userEmailKey = 'app_user_email';

  // 기존 게임 키들
  static const String _sudokuMaxLevelKey = 'max_unlocked_level';
  static const String _sudokuRankMapKey = 'last_checked_rank_map';
  static const String _spiderMaxLevelKey = 'max_unlocked_spider_level';
  static const String _spiderRankMapKey = 'last_checked_spider_rank_map';
  static const String _mathQuizMaxLevelKey = 'max_unlocked_mathquiz_level';
  static const String _mathQuizRankMapKey = 'last_checked_mathquiz_rank_map';
  static const String _colorMatchMaxLevelKey = 'max_unlocked_colormatch_level';
  static const String _colorMatchRankMapKey = 'last_checked_colormatch_rank_map';
  static const String _sequenceMaxLevelKey = 'max_unlocked_sequence_level';
  static const String _sequenceRankMapKey = 'last_checked_sequence_rank_map';
  static const String _cardFlipMaxLevelKey = 'max_unlocked_cardflip_level';
  static const String _cardFlipRankMapKey = 'last_checked_cardflip_rank_map';

  // 🔽 [🔥 신규] 다른 그림 찾기 키 추가
  static const String _findDiffMaxLevelKey = 'max_unlocked_finddiff_level';
  static const String _findDiffRankMapKey = 'last_checked_finddiff_rank_map';

  final _storage = const FlutterSecureStorage();

  IOSOptions _getIOSOptions() => const IOSOptions();
  AndroidOptions _getAndroidOptions() => const AndroidOptions(encryptedSharedPreferences: true);

  Future<UserSession> getUserSession() async {
    final userId = await getOrCreateUserId(); 
    final userName = await getSavedUserName();
    final loginProvider = await _storage.read(key: _loginProviderKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions()) ?? "guest";
    final email = await _storage.read(key: _userEmailKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    return UserSession(userId: userId, userName: userName, loginProvider: loginProvider, email: email);
  }

  Future<String> getOrCreateUserId() async {
    String? userId = await _storage.read(key: _userIdKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    if (userId == null) {
      userId = const Uuid().v4();
      await _storage.write(key: _userIdKey, value: userId, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    }
    return userId;
  }

  Future<String?> getSavedUserName() async {
    return await _storage.read(key: _userNameKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
  }

  Future<void> saveUserName(String name) async {
    await _storage.write(key: _userNameKey, value: name, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
  }

  Future<UserSession> saveSocialLogin({required String newUserId, required String newUserName, required String newEmail, required String provider}) async {
    await _storage.write(key: _userIdKey, value: newUserId, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    await _storage.write(key: _userNameKey, value: newUserName, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    await _storage.write(key: _userEmailKey, value: newEmail, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    await _storage.write(key: _loginProviderKey, value: provider, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    return UserSession(userId: newUserId, userName: newUserName, loginProvider: provider, email: newEmail);
  }

  Future<UserSession> logout() async {
    await _storage.delete(key: _userNameKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    await _storage.delete(key: _userEmailKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    await _storage.delete(key: _loginProviderKey, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    return await getUserSession(); 
  }

  // 7. [수정] 최대 레벨 가져오기
  Future<int> getMaxUnlockedLevel({String gameType = 'SUDOKU'}) async {
    String key;
    switch (gameType) {
      case 'SPIDER': key = _spiderMaxLevelKey; break;
      case 'MATH_QUIZ': key = _mathQuizMaxLevelKey; break;
      case 'COLOR_MATCH': key = _colorMatchMaxLevelKey; break;
      case 'SEQUENCE': key = _sequenceMaxLevelKey; break;
      case 'CARD_FLIP': key = _cardFlipMaxLevelKey; break;
      case 'FIND_DIFF': key = _findDiffMaxLevelKey; break; // 👈 추가
      default: key = _sudokuMaxLevelKey;
    }
    String? levelString = await _storage.read(key: key, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
    return int.parse(levelString ?? '1');
  }

  // 8. [수정] 최대 레벨 저장하기
  Future<void> saveMaxUnlockedLevel(int level, {String gameType = 'SUDOKU'}) async {
    String key;
    switch (gameType) {
      case 'SPIDER': key = _spiderMaxLevelKey; break;
      case 'MATH_QUIZ': key = _mathQuizMaxLevelKey; break;
      case 'COLOR_MATCH': key = _colorMatchMaxLevelKey; break;
      case 'SEQUENCE': key = _sequenceMaxLevelKey; break;
      case 'CARD_FLIP': key = _cardFlipMaxLevelKey; break;
      case 'FIND_DIFF': key = _findDiffMaxLevelKey; break; // 👈 추가
      default: key = _sudokuMaxLevelKey;
    }
    await _storage.write(key: key, value: level.toString(), iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
  }

  // 9. [수정] 마지막 랭킹 맵 가져오기
  Future<Map<int, int>> getLastSavedRankMap({String gameType = 'SUDOKU'}) async {
    String key;
    switch (gameType) {
      case 'SPIDER': key = _spiderRankMapKey; break;
      case 'MATH_QUIZ': key = _mathQuizRankMapKey; break;
      case 'COLOR_MATCH': key = _colorMatchRankMapKey; break;
      case 'SEQUENCE': key = _sequenceRankMapKey; break;
      case 'CARD_FLIP': key = _cardFlipRankMapKey; break;
      case 'FIND_DIFF': key = _findDiffRankMapKey; break; // 👈 추가
      default: key = _sudokuRankMapKey;
    }
    String? jsonString = await _storage.read(key: key, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());

    if (jsonString == null) return {};
    try {
      final Map<String, dynamic> decodedMap = jsonDecode(jsonString);
      return decodedMap.map((key, value) => MapEntry(int.parse(key), value as int));
    } catch (e) {
      return {};
    }
  }

  // 10. [수정] 마지막 랭킹 맵 저장하기
  Future<void> saveLastRankMap(Map<int, int> rankMap, {String gameType = 'SUDOKU'}) async {
    String key;
    switch (gameType) {
      case 'SPIDER': key = _spiderRankMapKey; break;
      case 'MATH_QUIZ': key = _mathQuizRankMapKey; break;
      case 'COLOR_MATCH': key = _colorMatchRankMapKey; break;
      case 'SEQUENCE': key = _sequenceRankMapKey; break;
      case 'CARD_FLIP': key = _cardFlipRankMapKey; break;
      case 'FIND_DIFF': key = _findDiffRankMapKey; break; // 👈 추가
      default: key = _sudokuRankMapKey;
    }
    
    final Map<String, int> stringKeyMap = rankMap.map((key, value) => MapEntry(key.toString(), value));
    String jsonString = jsonEncode(stringKeyMap);
    await _storage.write(key: key, value: jsonString, iOptions: _getIOSOptions(), aOptions: _getAndroidOptions());
  }
}