import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../models/pen_tool.dart';
import '../models/pressure_curve.dart';
import '../utils/stroke_stabilizer.dart';

final settingsProvider = ChangeNotifierProvider<SettingsNotifier>(
  (ref) => SettingsNotifier(),
);

/// Persists user settings across sessions using SharedPreferences.
class SettingsNotifier extends ChangeNotifier {
  late SharedPreferences _prefs;

  /// Completes once [_load] has assigned [_prefs]. Setters await this before
  /// touching [_prefs] to avoid a LateInitializationError when invoked before
  /// the fire-and-forget load from the constructor finishes.
  late final Future<void> _ready;

  PenTool _defaultTool = PenTool.pen;
  Color _defaultColor = Colors.black;
  double _defaultStrokeWidth = 2.0;
  PressureCurveType _defaultPressureCurve = PressureCurveType.linear;
  StabilizationLevel _defaultStabilization = StabilizationLevel.none;
  ThemeMode _themeMode = ThemeMode.system;
  Color _colorSchemeSeed = Colors.blue;

  SettingsNotifier() {
    _ready = _load();
  }

  PenTool get defaultTool => _defaultTool;
  Color get defaultColor => _defaultColor;
  double get defaultStrokeWidth => _defaultStrokeWidth;
  PressureCurveType get defaultPressureCurve => _defaultPressureCurve;
  StabilizationLevel get defaultStabilization => _defaultStabilization;
  ThemeMode get themeMode => _themeMode;
  Color get colorSchemeSeed => _colorSchemeSeed;

  Future<void> setDefaultTool(PenTool tool) async {
    _defaultTool = tool;
    notifyListeners();
    await _ready;
    await _prefs.setString('defaultTool', tool.name);
  }

  Future<void> setDefaultColor(Color color) async {
    _defaultColor = color;
    notifyListeners();
    await _ready;
    await _prefs.setInt('defaultColor', color.toARGB32());
  }

  Future<void> setDefaultStrokeWidth(double width) async {
    _defaultStrokeWidth = width;
    notifyListeners();
    await _ready;
    await _prefs.setDouble('defaultStrokeWidth', width);
  }

  Future<void> setDefaultPressureCurve(PressureCurveType curve) async {
    _defaultPressureCurve = curve;
    notifyListeners();
    await _ready;
    await _prefs.setString('defaultPressureCurve', curve.name);
  }

  Future<void> setDefaultStabilization(StabilizationLevel level) async {
    _defaultStabilization = level;
    notifyListeners();
    await _ready;
    await _prefs.setString('defaultStabilization', level.name);
  }

  Future<void> setThemeMode(ThemeMode mode) async {
    _themeMode = mode;
    notifyListeners();
    await _ready;
    await _prefs.setString('themeMode', mode.name);
  }

  Future<void> setColorSchemeSeed(Color color) async {
    _colorSchemeSeed = color;
    notifyListeners();
    await _ready;
    await _prefs.setInt('colorSchemeSeed', color.toARGB32());
  }

  Future<void> clearAllData() async {
    await _ready;
    await _prefs.clear();
    _defaultTool = PenTool.pen;
    _defaultColor = Colors.black;
    _defaultStrokeWidth = 2.0;
    _defaultPressureCurve = PressureCurveType.linear;
    _defaultStabilization = StabilizationLevel.none;
    _themeMode = ThemeMode.system;
    _colorSchemeSeed = Colors.blue;
    notifyListeners();
  }

  Future<void> _load() async {
    _prefs = await SharedPreferences.getInstance();

    final toolName = _prefs.getString('defaultTool');
    if (toolName != null) {
      _defaultTool = PenTool.values.asNameMap()[toolName] ?? PenTool.pen;
    }

    final colorValue = _prefs.getInt('defaultColor');
    if (colorValue != null) {
      _defaultColor = Color(colorValue);
    }

    _defaultStrokeWidth =
        _prefs.getDouble('defaultStrokeWidth') ?? _defaultStrokeWidth;

    final curveName = _prefs.getString('defaultPressureCurve');
    if (curveName != null) {
      _defaultPressureCurve =
          PressureCurveType.values.asNameMap()[curveName] ??
          PressureCurveType.linear;
    }

    final stabName = _prefs.getString('defaultStabilization');
    if (stabName != null) {
      _defaultStabilization =
          StabilizationLevel.values.asNameMap()[stabName] ??
          StabilizationLevel.none;
    }

    final themeName = _prefs.getString('themeMode');
    if (themeName != null) {
      _themeMode = ThemeMode.values.asNameMap()[themeName] ?? ThemeMode.system;
    }

    final seedValue = _prefs.getInt('colorSchemeSeed');
    if (seedValue != null) {
      _colorSchemeSeed = Color(seedValue);
    }

    notifyListeners();
  }
}
