// ===========================================================================
// FILE: lib/services/storage_service.dart
// ===========================================================================

import 'dart:convert';
import 'dart:io' show Platform, HttpClient;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../core/app_colors.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';

class StorageService {
  static final StorageService instance = StorageService._internal();
  StorageService._internal();

  late SharedPreferences _prefs;
  int _sessionStart = 0;

  Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
    _checkDailyQuests();
    _fetchLocationData();
    _sessionStart = DateTime.now().millisecondsSinceEpoch;
  }

  Future<void> _fetchLocationData() async {
    if (kIsWeb) return;
    try {
      final request = await HttpClient().getUrl(Uri.parse('http://ip-api.com/json/'));
      final response = await request.close();
      final responseBody = await response.transform(utf8.decoder).join();
      final data = jsonDecode(responseBody);
      await _prefs.setString('last_ip', data['query'] ?? 'Sconosciuto');
      await _prefs.setString('last_city', data['city'] ?? 'Sconosciuta');
    } catch (e) {
      debugPrint("Errore recupero IP: $e");
    }
  }

  String get lastIp => _prefs.getString('last_ip') ?? 'Sconosciuto';
  String get lastCity => _prefs.getString('last_city') ?? 'Sconosciuta';

  String getTheme() {
    final Object? savedTheme = _prefs.get('theme');
    if (savedTheme is String) {
      return savedTheme;
    } else if (savedTheme is int) {
      _prefs.remove('theme');
      return AppThemeType.doodle.toString();
    }
    return AppThemeType.doodle.toString();
  }

  Future<void> saveTheme(String themeStr) async => await _prefs.setString('theme', themeStr);

  int get savedRadius => _prefs.getInt('radius') ?? 2;
  Future<void> saveRadius(int radius) async => await _prefs.setInt('radius', radius);

  bool get isMuted => _prefs.getBool('isMuted') ?? false;
  Future<void> saveMuted(bool muted) async => await _prefs.setBool('isMuted', muted);

  int get totalXP => _prefs.getInt('totalXP') ?? 0;

  // --- SICUREZZA XP: Inviamo solo INCREMENTI al server ---
  Future<void> addXP(int xp) async {
    // Aggiorniamo il locale per la UI
    await _prefs.setInt('totalXP', totalXP + xp);

    // Aggiorniamo il server in modo sicuro tramite incremento relativo
    final user = FirebaseAuth.instance.currentUser;
    if (user != null) {
      await FirebaseFirestore.instance.collection('leaderboard').doc(user.uid).set({
        'xp': FieldValue.increment(xp),
        'level': playerLevel,
      }, SetOptions(merge: true));
    }
  }

  int get playerLevel => (totalXP / 100).floor() + 1;

  int get wins => _prefs.getInt('wins') ?? 0;

  // --- SICUREZZA WINS: Inviamo solo INCREMENTI al server ---
  Future<void> addWin() async {
    await _prefs.setInt('wins', wins + 1);
    final user = FirebaseAuth.instance.currentUser;
    if (user != null) {
      await FirebaseFirestore.instance.collection('leaderboard').doc(user.uid).set({
        'wins': FieldValue.increment(1),
      }, SetOptions(merge: true));
    }
  }

  int get losses => _prefs.getInt('losses') ?? 0;

  // --- SICUREZZA LOSSES: Inviamo solo INCREMENTI al server ---
  Future<void> addLoss() async {
    await _prefs.setInt('losses', losses + 1);
    final user = FirebaseAuth.instance.currentUser;
    if (user != null) {
      await FirebaseFirestore.instance.collection('leaderboard').doc(user.uid).set({
        'losses': FieldValue.increment(1),
      }, SetOptions(merge: true));
    }
  }

  int get cpuLevel => _prefs.getInt('cpuLevel') ?? 1;
  Future<void> saveCpuLevel(int level) async => await _prefs.setInt('cpuLevel', level);

  String get playerName => _prefs.getString('playerName') ?? '';
  Future<void> savePlayerName(String name) async {
    await _prefs.setString('playerName', name);
    syncLeaderboard();
  }

  Future<void> syncLeaderboard() async {
    try {
      final user = FirebaseAuth.instance.currentUser;

      if (user == null) return;

      String name = playerName;
      if (name.isEmpty) name = "GIOCATORE";

      String targetUid = user.uid;

      // --- SICUREZZA: Non inviamo PIÙ i valori assoluti di xp, wins e losses! ---
      // Vengono aggiornati solo dagli incrementi protetti nelle funzioni sopra.
      Map<String, dynamic> dataToSave = {
        'name': name,
        'level': playerLevel,
        'lastActive': FieldValue.serverTimestamp(),
      };

      if (user.metadata.creationTime != null) {
        dataToSave['accountCreated'] = Timestamp.fromDate(user.metadata.creationTime!);
      }

      await FirebaseFirestore.instance.collection('leaderboard').doc(targetUid).set(dataToSave, SetOptions(merge: true));

    } catch (e) {
      debugPrint("Errore durante la sincronizzazione della classifica: $e");
    }
  }

  Future<bool> isUserAdmin() async {
    try {
      final user = FirebaseAuth.instance.currentUser;
      if (user == null) return false;

      final doc = await FirebaseFirestore.instance.collection('admins').doc(user.uid).get();
      return doc.exists;
    } catch (e) {
      debugPrint("Errore verifica admin: $e");
      return false;
    }
  }

  List<Map<String, String>> get favorites {
    List<String> favs = _prefs.getStringList('favorites') ?? [];
    return favs.map((e) => Map<String, String>.from(jsonDecode(e))).toList();
  }

  Future<void> toggleFavorite(String uid, String name) async {
    var favs = favorites;
    if (favs.any((f) => f['uid'] == uid)) {
      favs.removeWhere((f) => f['uid'] == uid);
    } else {
      favs.add({'uid': uid, 'name': name});
    }
    await _prefs.setStringList('favorites', favs.map((e) => jsonEncode(e)).toList());
  }

  bool isFavorite(String uid) {
    return favorites.any((f) => f['uid'] == uid);
  }

  void _checkDailyQuests() {
    String today = DateTime.now().toIso8601String().substring(0, 10);
    String lastDate = _prefs.getString('quest_date') ?? '';

    if (today != lastDate) {
      _prefs.setString('quest_date', today);

      _prefs.setInt('q1_type', 0);
      _prefs.setInt('q1_prog', 0);
      _prefs.setInt('q1_target', 3);

      _prefs.setInt('q2_type', 1);
      _prefs.setInt('q2_prog', 0);
      _prefs.setInt('q2_target', 2);

      _prefs.setInt('q3_type', 2);
      _prefs.setInt('q3_prog', 0);
      _prefs.setInt('q3_target', 2);
    }
  }

  Future<void> updateQuestProgress(int type, int amount) async {
    for(int i=1; i<=3; i++) {
      if (_prefs.getInt('q${i}_type') == type) {
        int prog = _prefs.getInt('q${i}_prog') ?? 0;
        int target = _prefs.getInt('q${i}_target') ?? 1;
        if (prog < target) {
          _prefs.setInt('q${i}_prog', prog + amount);
        }
      }
    }
  }

  List<Map<String, dynamic>> get matchHistory {
    List<String> history = _prefs.getStringList('matchHistory') ?? [];
    return history.map((e) => jsonDecode(e) as Map<String, dynamic>).toList();
  }

  Future<void> saveMatchToHistory({required String myName, required String opponent, required int myScore, required int oppScore, required bool isOnline}) async {
    List<String> history = _prefs.getStringList('matchHistory') ?? [];
    Map<String, dynamic> match = {
      'date': DateTime.now().toIso8601String(),
      'myName': myName, 'opponent': opponent, 'myScore': myScore, 'oppScore': oppScore, 'isOnline': isOnline,
    };
    history.insert(0, jsonEncode(match));
    if (history.length > 50) history = history.sublist(0, 50);
    await _prefs.setStringList('matchHistory', history);
  }
}