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

class ScoreManager {
  static const String _todayScoreKey = 'today_score';
  static const String _totalScoreKey = 'total_score';
  static const String _dailyHistoryKey = 'daily_history';
  static const String _lastDateKey = 'last_date';

  static int _todayScore = 0;
  static int _totalScore = 0;
  static Map<String, int> _dailyHistory = {};

  static int get todayScore => _todayScore;
  static int get totalScore => _totalScore;
  static Map<String, int> get dailyHistory => Map.from(_dailyHistory);

  /// Initialize the score manager - loads saved data
  static Future<void> initialize() async {
    await _loadScores();
    await _checkNewDay();
  }

  /// Add points to today's score
  static Future<void> addScore(int points) async {
    _todayScore += points;
    _totalScore += points;
    await _saveScores();
  }

  /// Reset today's score (for testing purposes)
  static Future<void> resetTodayScore() async {
    _todayScore = 0;
    await _saveScores();
  }

  /// Get scores for the last N days (for charts)
  static List<MapEntry<String, int>> getLastDaysScores(int days) {
    final now = DateTime.now();
    final result = <MapEntry<String, int>>[];

    for (int i = days - 1; i >= 0; i--) {
      final date = now.subtract(Duration(days: i));
      final dateStr = _formatDate(date);
      final score = _dailyHistory[dateStr] ?? 0;
      result.add(MapEntry(dateStr, score));
    }

    return result;
  }

  /// Get weekly totals for the last N weeks
  static List<MapEntry<String, int>> getWeeklyScores(int weeks) {
    final now = DateTime.now();
    final result = <MapEntry<String, int>>[];

    for (int i = weeks - 1; i >= 0; i--) {
      final weekStart = now.subtract(Duration(days: now.weekday - 1 + (i * 7)));
      
      int weekTotal = 0;
      for (int day = 0; day < 7; day++) {
        final date = weekStart.add(Duration(days: day));
        final dateStr = _formatDate(date);
        weekTotal += _dailyHistory[dateStr] ?? 0;
      }

      final weekLabel = 'Week of ${_formatDate(weekStart)}';
      result.add(MapEntry(weekLabel, weekTotal));
    }

    return result;
  }

  /// Get total bubbles popped (approximate based on score)
  static int get totalBubblesPopped => _totalScore ~/ 10; // 10 points per bubble

  /// Get average daily score
  static double get averageDailyScore {
    if (_dailyHistory.isEmpty) return 0.0;
    final total = _dailyHistory.values.fold(0, (a, b) => a + b);
    return total / _dailyHistory.length;
  }

  /// Get current streak (consecutive days with score > 0)
  static int get currentStreak {
    final now = DateTime.now();
    int streak = 0;

    for (int i = 0; i < 365; i++) { // Check up to a year
      final date = now.subtract(Duration(days: i));
      final dateStr = _formatDate(date);
      final score = _dailyHistory[dateStr] ?? 0;

      if (score > 0) {
        streak++;
      } else {
        break;
      }
    }

    return streak;
  }

  /// Get best day score
  static int get bestDayScore {
    if (_dailyHistory.isEmpty) return _todayScore;
    return _dailyHistory.values.fold(_todayScore, (a, b) => a > b ? a : b);
  }

  static Future<void> _loadScores() async {
    final prefs = await SharedPreferences.getInstance();
    
    // Handle potential type mismatches from previous versions
    try {
      _todayScore = prefs.getInt(_todayScoreKey) ?? 0;
    } catch (e) {
      // Clean up corrupted data
      await prefs.remove(_todayScoreKey);
      _todayScore = 0;
    }
    
    try {
      _totalScore = prefs.getInt(_totalScoreKey) ?? 0;
    } catch (e) {
      // Clean up corrupted data
      await prefs.remove(_totalScoreKey);
      _totalScore = 0;
    }
    
    final historyJson = prefs.getString(_dailyHistoryKey) ?? '{}';
    try {
      final historyMap = json.decode(historyJson) as Map<String, dynamic>;
      _dailyHistory = historyMap.map((key, value) => MapEntry(key, value as int));
    } catch (e) {
      _dailyHistory = {};
      // Clean up corrupted data
      await prefs.remove(_dailyHistoryKey);
    }
  }

  static Future<void> _saveScores() async {
    final prefs = await SharedPreferences.getInstance();
    
    await prefs.setInt(_todayScoreKey, _todayScore);
    await prefs.setInt(_totalScoreKey, _totalScore);
    await prefs.setString(_lastDateKey, DateTime.now().toIso8601String().split('T')[0]);
    
    // Save today's score to history
    final today = _formatDate(DateTime.now());
    _dailyHistory[today] = _todayScore;
    
    final historyJson = json.encode(_dailyHistory);
    await prefs.setString(_dailyHistoryKey, historyJson);
  }

  static Future<void> _checkNewDay() async {
    final prefs = await SharedPreferences.getInstance();
    final lastDate = prefs.getString(_lastDateKey);
    final today = _formatDate(DateTime.now());

    if (lastDate != today) {
      // New day - save yesterday's score and reset today's
      if (lastDate != null && _todayScore > 0) {
        _dailyHistory[lastDate] = _todayScore;
      }
      _todayScore = 0;
      await prefs.setString(_lastDateKey, today);
      await _saveScores();
    }
  }

  static String _formatDate(DateTime date) {
    return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
  }

  /// Clean up old data (keep only last 365 days)
  static Future<void> cleanupOldData() async {
    final cutoffDate = DateTime.now().subtract(const Duration(days: 365));
    final cutoffStr = _formatDate(cutoffDate);

    _dailyHistory.removeWhere((date, score) => date.compareTo(cutoffStr) < 0);
    await _saveScores();
  }
}