import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../core/contracts/library.dart';
import '../core/media/media_range_detector.dart';
import 'shared/settings_persistence.dart';

enum VersionPriority {
  dolbyVision('杜比视界优先'),
  hdr('HDR 优先'),
  sdr('SDR 优先'),
  highBitrate('高码率优先'),
  lowBitrate('低码率优先'),
  highFramerate('高帧率优先'),
  largeFile('大文件优先');

  final String label;
  const VersionPriority(this.label);
}

class VersionPriorityState {
  final List<VersionPriority> activePriorities;
  const VersionPriorityState({this.activePriorities = const []});
}

class VersionPriorityNotifier extends AsyncNotifier<VersionPriorityState>
    with SettingsPersistence {
  static const _key = 'smplayer.version_priorities';

  @override
  Future<VersionPriorityState> build() async {
    final prefs = await getPrefs();
    final raw = prefs.getStringList(_key);
    if (raw == null) return const VersionPriorityState();
    final priorities = raw
        .map((name) {
          try {
            return VersionPriority.values.byName(name);
          } catch (_) {
            return null;
          }
        })
        .whereType<VersionPriority>()
        .toList();
    return VersionPriorityState(activePriorities: priorities);
  }

  Future<void> _save(List<VersionPriority> list) async {
    state = AsyncValue.data(VersionPriorityState(activePriorities: list));
    await persistField(_key, list.map((p) => p.name).toList());
  }

  Future<void> toggle(VersionPriority p) async {
    final current = List<VersionPriority>.from(
      state.value?.activePriorities ?? [],
    );
    current.contains(p) ? current.remove(p) : current.add(p);
    await _save(current);
  }

  Future<void> setPriorities(List<VersionPriority> list) => _save(list);
}

final versionPriorityProvider =
    AsyncNotifierProvider<VersionPriorityNotifier, VersionPriorityState>(
      VersionPriorityNotifier.new,
    );

List<EmbyRawMediaSource> sortMediaSources(
  List<EmbyRawMediaSource> sources,
  List<VersionPriority> priorities,
) {
  if (priorities.isEmpty || sources.length <= 1) return sources;
  final sorted = List<EmbyRawMediaSource>.from(sources);
  sorted.sort((a, b) => compareMediaSourcesByPriority(a, b, priorities));
  return sorted;
}


int compareMediaSourcesByPriority(
  EmbyRawMediaSource a,
  EmbyRawMediaSource b,
  List<VersionPriority> priorities,
) {
  for (final p in priorities) {
    final cmp = _compareByRule(a, b, p);
    if (cmp != 0) return cmp;
  }
  return 0;
}

int _compareByRule(
  EmbyRawMediaSource a,
  EmbyRawMediaSource b,
  VersionPriority rule,
) {
  switch (rule) {
    case VersionPriority.dolbyVision:
      return _boolDesc(isDolbyVision(a), isDolbyVision(b));
    case VersionPriority.hdr:
      return _boolDesc(isHdr(a), isHdr(b));
    case VersionPriority.sdr:
      return _boolDesc(!isHdr(a), !isHdr(b));
    case VersionPriority.highBitrate:
      return (b.Bitrate ?? 0).compareTo(a.Bitrate ?? 0);
    case VersionPriority.lowBitrate:
      return (a.Bitrate ?? 0).compareTo(b.Bitrate ?? 0);
    case VersionPriority.highFramerate:
      return getFrameRate(b).compareTo(getFrameRate(a));
    case VersionPriority.largeFile:
      return (b.Size ?? 0).compareTo(a.Size ?? 0);
  }
}

int _boolDesc(bool a, bool b) {
  if (a == b) return 0;
  return a ? -1 : 1;
}
