import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import '../auth/auth_provider.dart' show secureStorageProvider;

/// Operator-tunable cache settings. Persisted via
/// flutter_secure_storage on the same device.
///
/// #427 S2: the single `capBytes` is replaced by two independent
/// budgets — Liked and Rolling-recent — each defaulting to 5GB.
/// Bucketing is by liked-ness (a cached track currently in the
/// user's liked set is charged to Liked; everything else to
/// Rolling), so the dedup is storage-only and never filters
/// playback. The old `cache_cap_bytes` key is intentionally not
/// migrated; defaults reapply (a one-time re-tune, not data loss).
class CacheSettings {
  const CacheSettings({
    required this.likedCapBytes,
    required this.rollingCapBytes,
    required this.prefetchWindow,
    required this.cacheLikedTracks,
  });

  /// Liked-bucket budget. 0 = unlimited.
  final int likedCapBytes;

  /// Rolling (recently-played) budget. 0 = unlimited.
  final int rollingCapBytes;

  /// 1..10. Number of next-tracks the prefetcher pre-downloads.
  final int prefetchWindow;

  /// When true, every like_track event triggers a pin with source autoLiked.
  final bool cacheLikedTracks;

  CacheSettings copyWith({
    int? likedCapBytes,
    int? rollingCapBytes,
    int? prefetchWindow,
    bool? cacheLikedTracks,
  }) =>
      CacheSettings(
        likedCapBytes: likedCapBytes ?? this.likedCapBytes,
        rollingCapBytes: rollingCapBytes ?? this.rollingCapBytes,
        prefetchWindow: prefetchWindow ?? this.prefetchWindow,
        cacheLikedTracks: cacheLikedTracks ?? this.cacheLikedTracks,
      );

  static const _fiveGiB = 5 * 1024 * 1024 * 1024;

  static const defaults = CacheSettings(
    likedCapBytes: _fiveGiB,
    rollingCapBytes: _fiveGiB,
    prefetchWindow: 5,
    cacheLikedTracks: true,
  );
}

class CacheSettingsController extends AsyncNotifier<CacheSettings> {
  static const _kLikedCap = 'cache_liked_cap_bytes';
  static const _kRollingCap = 'cache_rolling_cap_bytes';
  static const _kPrefetch = 'cache_prefetch_window';
  static const _kCacheLiked = 'cache_liked_tracks';

  late FlutterSecureStorage _storage;

  @override
  Future<CacheSettings> build() async {
    _storage = ref.read(secureStorageProvider);
    final likedCap = await _storage.read(key: _kLikedCap);
    final rollingCap = await _storage.read(key: _kRollingCap);
    final pre = await _storage.read(key: _kPrefetch);
    final liked = await _storage.read(key: _kCacheLiked);
    return CacheSettings(
      likedCapBytes: likedCap == null
          ? CacheSettings.defaults.likedCapBytes
          : int.tryParse(likedCap) ?? CacheSettings.defaults.likedCapBytes,
      rollingCapBytes: rollingCap == null
          ? CacheSettings.defaults.rollingCapBytes
          : int.tryParse(rollingCap) ?? CacheSettings.defaults.rollingCapBytes,
      prefetchWindow: pre == null
          ? CacheSettings.defaults.prefetchWindow
          : (int.tryParse(pre) ?? 5).clamp(1, 10),
      cacheLikedTracks: liked == null
          ? CacheSettings.defaults.cacheLikedTracks
          : liked == 'true',
    );
  }

  Future<void> setLikedCapBytes(int bytes) async {
    await _storage.write(key: _kLikedCap, value: bytes.toString());
    state = AsyncData(state.value!.copyWith(likedCapBytes: bytes));
  }

  Future<void> setRollingCapBytes(int bytes) async {
    await _storage.write(key: _kRollingCap, value: bytes.toString());
    state = AsyncData(state.value!.copyWith(rollingCapBytes: bytes));
  }

  Future<void> setPrefetchWindow(int n) async {
    final clamped = n.clamp(1, 10);
    await _storage.write(key: _kPrefetch, value: clamped.toString());
    state = AsyncData(state.value!.copyWith(prefetchWindow: clamped));
  }

  Future<void> setCacheLikedTracks(bool on) async {
    await _storage.write(key: _kCacheLiked, value: on.toString());
    state = AsyncData(state.value!.copyWith(cacheLikedTracks: on));
  }
}

final cacheSettingsProvider =
    AsyncNotifierProvider<CacheSettingsController, CacheSettings>(
        CacheSettingsController.new);
