import 'dart:async';
import 'dart:convert'; // 导入 json 编码解码
import 'dart:io';

import 'package:puzzleweave/models/items.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:rate_my_app/rate_my_app.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';

///持久化存储数据
///全局类
class Persistence {
  late final SharedPreferences _prefs;

  Persistence._internal();
  static final Persistence _instance = Persistence._internal();
  factory Persistence() => _instance;

  int get projectId {
    if (Platform.isAndroid) {
      return 19; // 暂定，需要跟阿淼确认
    } else if (Platform.isIOS) {
      return 20;
    }
    return 0;
  }

  String get libraryName {
    if (Platform.isAndroid) {
      return "android";
    } else if (Platform.isIOS) {
      return "ios";
    }
    return "unkown";
  }

  late String packageVersion;

  ///初始化并给各参数分配默认值
  Future<void> initialize() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    packageVersion = packageInfo.version;

    _prefs = await SharedPreferences.getInstance();

    //系统
    _uuid = PreferencesValue<String>('uuid', const Uuid().v4(), _prefs);
    _firstRun = PreferencesValue<bool>('first_run', true, _prefs);
    _firstRunTime = PreferencesValue<DateTime>('first_run_time', DateTime.now(), _prefs, saveDefault: true);
    _lastRunTime = PreferencesValue<DateTime>('last_run_time', DateTime.now(), _prefs, saveDefault: true);
    _lastDailyRewardTime = PreferencesValue<DateTime>('last_daily_reward_time', DateTime.now().subtract(const Duration(days: 1)), _prefs);

    //评分
    _rating = PreferencesValue<double>('rating', 0, _prefs);
    _rateShowTimes = PreferencesValue<int>('rate_show_times', 0, _prefs);
    _rateLastShowTime = PreferencesValue<DateTime>('last_rate_show_time', DateTime.now().subtract(const Duration(days: 1)), _prefs);

    //settings
    _sound = PreferencesValue<bool>('sound', true, _prefs);
    _music = PreferencesValue<bool>('music', true, _prefs);
    _vibrate = PreferencesValue<bool>('vibrate', true, _prefs);
    _skin = PreferencesValue<int>('skin', 0, _prefs);

    //banner 广告收益
    _lastBannerPaidReportTimestamp = PreferencesValue<int>('last_banner_paid_report_timestamp', DateTime.now().millisecondsSinceEpoch, _prefs);
    _bannerPaidValueMicros = PreferencesValue<double>('banner_paid_value_micros', 0, _prefs);
    _allPaidValueMicros = PreferencesValue<double>('all_paid_value_micros', 0, _prefs);
    _tRoasCache = PreferencesValue<double>('troas_cache', 0, _prefs);

    // !!! 改造点：完成作品集 - 存储 Work 对象列表
    _completedWorks = PreferencesValue<List<Work>>(
      'completed_works',
      [],
      _prefs,
      encoder: (list) => list.map((w) => jsonEncode(w.toJson())).toList(), // 序列化
      decoder: (jsonList) => jsonList.map((jsonStr) => Work.fromJson(jsonDecode(jsonStr))).toList(), // 反序列化
    );
    // !!! 改造点：完成收藏图集 - 存储 Work 对象列表
    _completedCollections = PreferencesValue<List<Work>>(
      'completed_collections',
      [],
      _prefs,
      encoder: (list) => list.map((c) => jsonEncode(c.toJson())).toList(), // 序列化
      decoder: (jsonList) => jsonList.map((jsonStr) => Work.fromJson(jsonDecode(jsonStr))).toList(), // 反序列化
    );
  }

  // uuid
  late PreferencesValue<String> _uuid;
  String get uuid => _uuid.value;
  set uuid(String value) => _uuid.value = value;

  // firstRun
  late PreferencesValue<bool> _firstRun;
  bool get firstRun => _firstRun.value;
  set firstRun(bool value) => _firstRun.value = value;

  // 程序第一次运行
  late PreferencesValue<DateTime> _firstRunTime;
  DateTime get firstRunTime => _firstRunTime.value;
  set firstRunTime(DateTime value) => _firstRunTime.value = value;

  //程序最后一次运行时间
  late PreferencesValue<DateTime> _lastRunTime;
  DateTime get lastRunTime => _lastRunTime.value;
  set lastRunTime(DateTime value) => _lastRunTime.value = value;

  //上一次 daily reward 时间
  late PreferencesValue<DateTime> _lastDailyRewardTime;
  DateTime get lastDailyRewardTime => _lastDailyRewardTime.value;
  set lastDailyRewardTime(DateTime value) => _lastDailyRewardTime.value = value;

  //评分
  late PreferencesValue<double> _rating;
  double get rating => _rating.value;
  set rating(double value) => _rating.value = value;

  //评分弹框次数
  late PreferencesValue<int> _rateShowTimes;
  int get rateShowTimes => _rateShowTimes.value;
  set rateShowTimes(int value) => _rateShowTimes.value = value;

  //评分上次弹框时间
  late PreferencesValue<DateTime> _rateLastShowTime;
  DateTime get rateLastShowTime => _rateLastShowTime.value;
  set rateLastShowTime(DateTime value) => _rateLastShowTime.value = value;

  // 各种按键声音效果
  late PreferencesValue<bool> _sound;
  bool get sound => _sound.value;
  set sound(bool value) => _sound.value = value;

  // 背景音乐
  late PreferencesValue<bool> _music;
  bool get music => _music.value;
  set music(bool value) => _music.value = value;

  // 振动
  late PreferencesValue<bool> _vibrate;
  bool get vibrate => _vibrate.value;
  set vibrate(bool value) => _vibrate.value = value;

  // 皮肤方案
  late PreferencesValue<int> _skin;
  int get skin => _skin.value;
  set skin(int value) => _skin.value = value;

  // banner 上一次广告收益上报时间
  late PreferencesValue<int> _lastBannerPaidReportTimestamp;
  int get lastBannerPaidReportTimestamp => _lastBannerPaidReportTimestamp.value;
  set lastBannerPaidReportTimestamp(int value) => _lastBannerPaidReportTimestamp.value = value;

  // banner 广告收益累积金额
  late PreferencesValue<double> _bannerPaidValueMicros;
  double get bannerPaidValueMicros => _bannerPaidValueMicros.value;
  set bannerPaidValueMicros(double value) => _bannerPaidValueMicros.value = value;

  // 所有广告收益累积金额
  late PreferencesValue<double> _allPaidValueMicros;
  double get allPaidValueMicros => _allPaidValueMicros.value;
  set allPaidValueMicros(double value) => _allPaidValueMicros.value = value;

  // 广告收益缓存，单位美元
  late PreferencesValue<double> _tRoasCache;
  double get tRoasCache => _tRoasCache.value;
  set tRoasCache(double value) => _tRoasCache.value = value;

  // !!! 改造点：已完成作品集合
  late PreferencesValue<List<Work>> _completedWorks;
  List<Work> get completedWorks => _completedWorks.value;
  set completedWorks(List<Work> value) => _completedWorks.value = value;

  // !!! 改造点：已完成收藏集合
  late PreferencesValue<List<Work>> _completedCollections;
  List<Work> get completedCollections => _completedCollections.value;
  set completedCollections(List<Work> value) => _completedCollections.value = value;
}

///----------------------------
class PreferencesValue<T> {
  final String key;
  final T defaultValue;
  final SharedPreferences prefs;
  // 新增：用于自定义对象列表的编码和解码函数
  final List<String> Function(T value)? encoder;
  final T Function(List<String> jsonList)? decoder;

  late T _value;
  T get value => _value;
  set value(T v) {
    _value = v;
    if (_value is bool) {
      unawaited(prefs.setBool(key, _value as bool));
    } else if (_value is int) {
      unawaited(prefs.setInt(key, _value as int));
    } else if (_value is String) {
      unawaited(prefs.setString(key, _value as String));
    } else if (_value is double) {
      unawaited(prefs.setDouble(key, _value as double));
    } else if (_value is DateTime) {
      unawaited(prefs.setInt(key, (_value as DateTime).millisecondsSinceEpoch));
    } // !!! 改造点：处理 List<CompletedWork> 或 List<CompletedCollection>
    else if (_value is List<String> && encoder == null) {
      // 兼容旧的List<String>
      unawaited(prefs.setStringList(key, _value as List<String>));
    } else if (_value is List && encoder != null) {
      // 针对自定义对象列表
      unawaited(prefs.setStringList(key, encoder!(_value))); // 使用 encoder 编码
    }
    // 注意：这里没有对List<T> (非List<String>) 和非列表的自定义T进行处理，
    // 如果有其他非List<String>的自定义T需要持久化，需要在这里添加逻辑，
    // 例如通过 jsonEncode(value.toJson()) / T.fromJson(jsonDecode(string))
  }

  PreferencesValue(this.key, this.defaultValue, this.prefs, {bool saveDefault = false, this.encoder, this.decoder}) {
    _value = defaultValue;
    bool isExist = prefs.containsKey(key);
    if (_value is bool) {
      _value = (prefs.getBool(key) ?? defaultValue) as T;
      if (!isExist && saveDefault) unawaited(prefs.setBool(key, _value as bool));
    } else if (_value is int) {
      _value = (prefs.getInt(key) ?? defaultValue) as T;
      if (!isExist && saveDefault) unawaited(prefs.setInt(key, _value as int));
    } else if (_value is String) {
      _value = (prefs.getString(key) ?? defaultValue) as T;
      if (!isExist && saveDefault) unawaited(prefs.setString(key, _value as String));
    } else if (_value is double) {
      _value = (prefs.getDouble(key) ?? defaultValue) as T;
      if (!isExist && saveDefault) unawaited(prefs.setDouble(key, _value as double));
    } else if (_value is DateTime) {
      int? tmp = prefs.getInt(key);
      _value = (tmp == null ? defaultValue : DateTime.fromMillisecondsSinceEpoch(tmp)) as T;
      if (!isExist && saveDefault) unawaited(prefs.setInt(key, (_value as DateTime).millisecondsSinceEpoch));
    } // !!! 改造点：处理 List<CompletedWork> 或 List<CompletedCollection>
    else if (_value is List<String> && decoder == null) {
      // 兼容旧的List<String>
      _value = (prefs.getStringList(key) ?? defaultValue) as T;
      if (!isExist && saveDefault) unawaited(prefs.setStringList(key, _value as List<String>));
    } else if (_value is List && decoder != null) {
      // 针对自定义对象列表
      final List<String>? jsonList = prefs.getStringList(key);
      if (jsonList != null && jsonList.isNotEmpty) {
        _value = decoder!(jsonList); // 使用 decoder 反序列化
      } else {
        _value = defaultValue;
      }
      if (!isExist && saveDefault) unawaited(prefs.setStringList(key, encoder!(_value))); // 保存默认值
    }
  }
}
