import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../../view/pages/files/files.dart';
import '../file/fileSettings.dart';
import '../gradeAverages/gradeAveragesSettings.dart';
import '../holidays/holidaysSettings.dart';
import '../talk/talkSettings.dart';
import '../timetable/timetableSettings.dart';
import 'settings.dart';

class SettingsProvider extends ChangeNotifier {
  static const String _fieldName = "settings";

  late SharedPreferences _storage;
  late Settings _settings = _defaults();

  Settings val({bool write = false}) {
    if(write) {
      notifyListeners();
      Future.delayed(const Duration(milliseconds: 300)).then((_) => update());
    }
    return _settings;
  }

  SettingsProvider() {
    _readFromStorage();
  }

  void reset() async {
    _storage = await SharedPreferences.getInstance();
    _storage.remove(_fieldName);

    notifyListeners();
  }

  void _readFromStorage() async {
    _storage = await SharedPreferences.getInstance();

    try {
      _settings = Settings.fromJson(jsonDecode(_storage.getString(_fieldName)!));
    } catch(exception) {
      try {
        log("Settings were changed, trying to recover from old Settings: ${exception.toString()}");
        _settings = Settings.fromJson(_mergeSettings(jsonDecode(_storage.getString(_fieldName)!), _defaults().toJson()));
        log("Settings recovered successfully: ${_settings.toJson().toString()}");
      } catch(exception) {
        log("Settings are defective and not recoverable, using defaults: ${exception.toString()}");
        _settings = _defaults();
        log("Settings were reset to defaults!");
      }
    }

    notifyListeners();
  }

  void update() async {
    await _storage.setString(_fieldName, jsonEncode(_settings.toJson()));
  }

  Map<String, dynamic> _mergeSettings(Map<String, dynamic> oldMap, Map<String, dynamic> newMap) {
    Map<String, dynamic> mergedMap = Map.from(newMap);

    oldMap.forEach((key, value) {
      if (mergedMap.containsKey(key)) {
        if (value is Map<String, dynamic> && mergedMap[key] is Map<String, dynamic>) {
          mergedMap[key] = _mergeSettings(value, mergedMap[key]);
        } else {
          mergedMap[key] = value;
        }
      }
    });

    return mergedMap;
  }

  Settings _defaults() {
    return Settings(
      appTheme: ThemeMode.system,
      devToolsEnabled: false,
      gradeAveragesSettings: GradeAveragesSettings(
        useGradeSystem: true,
        inputs: []
      ),
      timetableSettings: TimetableSettings(
        zoom: 40,
      ),
      talkSettings: TalkSettings(
        sortFavoritesToTop: true,
        sortUnreadToTop: false,
      ),
      fileSettings: FileSettings(
        sortFoldersToTop: true,
        ascending: true,
        sortBy: SortOption.name
      ),
      holidaysSettings: HolidaysSettings(
        dismissedDisclaimer: false,
        showPastEvents: false,
      ),
    );
  }
}