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

import '../cache/audio_cache_manager.dart';
import '../cache/cache_settings_provider.dart';
import '../cache/sync_controller.dart';
import '../likes/likes_provider.dart' show likedIdsProvider;
import '../theme/theme_extension.dart';

/// Settings card: per-bucket usage, two cap selectors (Liked +
/// Recently-played), prefetch window, cache-liked toggle, Clear
/// cache + Sync now. #427 S2/S3: two independent budgets.
class StorageSection extends ConsumerStatefulWidget {
  const StorageSection({super.key});

  @override
  ConsumerState<StorageSection> createState() => _StorageSectionState();
}

class _StorageSectionState extends ConsumerState<StorageSection> {
  BucketUsage? _usage;
  bool _syncing = false;

  @override
  void initState() {
    super.initState();
    _refreshUsage();
  }

  Set<String> _likedSet() =>
      ref.read(likedIdsProvider).value?.tracks ?? const <String>{};

  Future<void> _refreshUsage() async {
    final mgr = ref.read(audioCacheManagerProvider);
    final u = await mgr.bucketUsage(_likedSet());
    if (mounted) setState(() => _usage = u);
  }

  String _fmtBytes(int? n) {
    if (n == null) return '—';
    if (n == 0) return '0 B';
    if (n < 1024) return '$n B';
    if (n < 1024 * 1024) return '${(n / 1024).toStringAsFixed(1)} KB';
    if (n < 1024 * 1024 * 1024) {
      return '${(n / 1024 / 1024).toStringAsFixed(1)} MB';
    }
    return '${(n / 1024 / 1024 / 1024).toStringAsFixed(2)} GB';
  }

  String _cap(int bytes) => bytes == 0 ? 'unlimited' : _fmtBytes(bytes);

  @override
  Widget build(BuildContext context) {
    final fs = Theme.of(context).extension<FabledSwordTheme>()!;
    final settings = ref.watch(cacheSettingsProvider);
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
      child: Card(
        color: fs.iron,
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: settings.when(
            loading: () => const Padding(
              padding: EdgeInsets.all(8),
              child: Center(child: CircularProgressIndicator()),
            ),
            error: (e, _) => Text('$e', style: TextStyle(color: fs.error)),
            data: (s) => Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Storage',
                    style: TextStyle(
                        color: fs.parchment,
                        fontSize: 18,
                        fontWeight: FontWeight.w500)),
                const SizedBox(height: 12),
                _usageRow('Liked', _usage?.liked, s.likedCapBytes, fs),
                const SizedBox(height: 4),
                _usageRow('Recently played', _usage?.rolling,
                    s.rollingCapBytes, fs),
                const SizedBox(height: 16),
                _capSelector(
                  'Liked cache limit',
                  const Key('liked_cap_selector'),
                  s.likedCapBytes,
                  (v) => ref
                      .read(cacheSettingsProvider.notifier)
                      .setLikedCapBytes(v),
                  s,
                  fs,
                ),
                const SizedBox(height: 8),
                _capSelector(
                  'Recently-played cache limit',
                  const Key('rolling_cap_selector'),
                  s.rollingCapBytes,
                  (v) => ref
                      .read(cacheSettingsProvider.notifier)
                      .setRollingCapBytes(v),
                  s,
                  fs,
                ),
                const SizedBox(height: 8),
                _prefetchSelector(s, fs),
                const SizedBox(height: 8),
                SwitchListTile(
                  key: const Key('cache_liked_toggle'),
                  contentPadding: EdgeInsets.zero,
                  title: Text('Cache liked tracks',
                      style: TextStyle(color: fs.parchment)),
                  value: s.cacheLikedTracks,
                  onChanged: (v) => ref
                      .read(cacheSettingsProvider.notifier)
                      .setCacheLikedTracks(v),
                ),
                const SizedBox(height: 12),
                Wrap(spacing: 8, runSpacing: 8, children: [
                  OutlinedButton(
                    key: const Key('clear_cache_button'),
                    onPressed: _confirmClear,
                    child: const Text('Clear cache'),
                  ),
                  OutlinedButton.icon(
                    key: const Key('sync_now_button'),
                    onPressed: _syncing
                        ? null
                        : () async {
                            setState(() => _syncing = true);
                            try {
                              await ref
                                  .read(syncControllerProvider.notifier)
                                  .sync();
                            } finally {
                              if (mounted) setState(() => _syncing = false);
                            }
                          },
                    icon: _syncing
                        ? const SizedBox(
                            width: 14,
                            height: 14,
                            child: CircularProgressIndicator(strokeWidth: 2),
                          )
                        : const Icon(LucideIcons.refresh_cw, size: 16),
                    label: const Text('Sync now'),
                  ),
                ]),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _usageRow(String label, int? used, int cap, FabledSwordTheme fs) {
    return Row(children: [
      Text(label, style: TextStyle(color: fs.ash)),
      const Spacer(),
      Text('${_fmtBytes(used)} / ${_cap(cap)}',
          style: TextStyle(color: fs.parchment)),
    ]);
  }

  static const _capOptions = [
    (1024 * 1024 * 1024, '1 GB'),
    (5 * 1024 * 1024 * 1024, '5 GB'),
    (10 * 1024 * 1024 * 1024, '10 GB'),
    (25 * 1024 * 1024 * 1024, '25 GB'),
    (0, 'Unlimited'),
  ];

  Widget _capSelector(
    String label,
    Key key,
    int current,
    Future<void> Function(int) setCap,
    CacheSettings s,
    FabledSwordTheme fs,
  ) {
    return Row(children: [
      Expanded(child: Text(label, style: TextStyle(color: fs.ash))),
      DropdownButton<int>(
        key: key,
        value: _capOptions.any((o) => o.$1 == current)
            ? current
            : 5 * 1024 * 1024 * 1024,
        items: _capOptions
            .map((o) => DropdownMenuItem(value: o.$1, child: Text(o.$2)))
            .toList(),
        onChanged: (v) async {
          if (v == null) return;
          await setCap(v);
          // Enforce immediately against the freshest settings.
          final fresh = ref.read(cacheSettingsProvider).value;
          if (fresh != null) {
            await ref.read(audioCacheManagerProvider).evictBuckets(
                  likedCap: fresh.likedCapBytes,
                  rollingCap: fresh.rollingCapBytes,
                  liked: _likedSet(),
                );
          }
          await _refreshUsage();
        },
      ),
    ]);
  }

  Widget _prefetchSelector(CacheSettings s, FabledSwordTheme fs) {
    const options = [1, 3, 5, 7, 10];
    return Row(children: [
      Expanded(
          child: Text('Pre-fetch ahead', style: TextStyle(color: fs.ash))),
      DropdownButton<int>(
        key: const Key('prefetch_selector'),
        value: options.contains(s.prefetchWindow) ? s.prefetchWindow : 5,
        items: options
            .map((n) => DropdownMenuItem(value: n, child: Text('$n tracks')))
            .toList(),
        onChanged: (v) async {
          if (v == null) return;
          await ref.read(cacheSettingsProvider.notifier).setPrefetchWindow(v);
        },
      ),
    ]);
  }

  Future<void> _confirmClear() async {
    final fs = Theme.of(context).extension<FabledSwordTheme>()!;
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Clear cache?'),
        content: const Text(
          'This deletes all cached audio (liked and recently-played). '
          'The next play of any track re-downloads from the server.',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(ctx, false),
            child: const Text('Cancel'),
          ),
          FilledButton(
            style: FilledButton.styleFrom(backgroundColor: fs.error),
            onPressed: () => Navigator.pop(ctx, true),
            child: const Text('Clear'),
          ),
        ],
      ),
    );
    if (confirmed != true) return;
    await ref.read(audioCacheManagerProvider).clearAll();
    await _refreshUsage();
  }
}
