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

import 'package:f0ckapp/models/mediaitem_model.dart';
import 'package:f0ckapp/services/api_service.dart';

const List<String> mediaTypes = ["alles", "image", "video", "audio"];
const List<String> mediaModes = ["sfw", "nsfw", "untagged", "all"];
const _unsetTag = Object();

class MediaState {
  final int typeIndex;
  final int modeIndex;
  final bool random;
  final String? tag;
  final int crossAxisCount;
  final List<MediaItem> mediaItems;
  final bool isLoading;
  final bool muted;

  const MediaState({
    this.typeIndex = 0,
    this.modeIndex = 0,
    this.random = false,
    this.tag,
    this.crossAxisCount = 0,
    this.mediaItems = const [],
    this.isLoading = false,
    this.muted = false,
  });

  MediaState replace({
    int? typeIndex,
    int? modeIndex,
    bool? random,
    Object? tag = _unsetTag,
    int? crossAxisCount,
    List<MediaItem>? mediaItems,
    bool? isLoading,
    bool? muted,
  }) {
    return MediaState(
      typeIndex: typeIndex ?? this.typeIndex,
      modeIndex: modeIndex ?? this.modeIndex,
      random: random ?? this.random,
      tag: identical(tag, _unsetTag) ? this.tag : tag as String?,
      crossAxisCount: crossAxisCount ?? this.crossAxisCount,
      mediaItems: mediaItems ?? this.mediaItems,
      isLoading: isLoading ?? this.isLoading,
      muted: muted ?? this.muted,
    );
  }
}

class MediaNotifier extends StateNotifier<MediaState> {
  final _storage = const FlutterSecureStorage(
    aOptions: AndroidOptions(encryptedSharedPreferences: true),
  );

  MediaNotifier() : super(const MediaState()) {
    _loadMutedState();
  }

  Future<void> _loadMutedState() async {
    final storedMuted = await _storage.read(key: 'muted');
    final isMuted = storedMuted == 'true';
    state = state.replace(muted: isMuted);
  }

  Future<void> _saveMutedState() async {
    await _storage.write(key: 'muted', value: state.muted.toString());
  }

  void setType(String type) {
    final newIndex = mediaTypes.indexOf(type);
    state = state.replace(typeIndex: newIndex);
    resetMedia();
  }

  void setMode(int modeIndex) {
    state = state.replace(modeIndex: modeIndex);
    resetMedia();
  }

  void toggleRandom() {
    state = state.replace(random: !state.random);
    resetMedia();
  }

  void setTag(String? tag) {
    state = state.replace(tag: tag);
    resetMedia();
  }

  void setCrossAxisCount(int count) {
    state = state.replace(crossAxisCount: count);
  }

  void resetMedia() {
    state = state.replace(mediaItems: []);
    loadMedia();
  }

  void addMediaItems(List<MediaItem> newItems) {
    final Set<int> existingIds = state.mediaItems
        .map((item) => item.id)
        .toSet();
    final List<MediaItem> filteredItems = newItems
        .where((item) => !existingIds.contains(item.id))
        .toList();
    if (filteredItems.isNotEmpty) {
      final List<MediaItem> updated = List<MediaItem>.from(state.mediaItems)
        ..addAll(filteredItems);
      state = state.replace(mediaItems: updated);
    }
  }

  List<MediaItem> mergeMediaItems(
    List<MediaItem> current,
    List<MediaItem> incoming,
  ) {
    final existingIds = current.map((item) => item.id).toSet();
    final newItems = incoming
        .where((item) => !existingIds.contains(item.id))
        .toList();
    return [...current, ...newItems];
  }

  Future<void> loadMedia({int? id}) async {
    if (state.isLoading) return;
    state = state.replace(isLoading: true);
    try {
      final older =
          id ?? (state.mediaItems.isNotEmpty ? state.mediaItems.last.id : null);
      final newMedia = await fetchMedia(
        older: older,
        type: mediaTypes[state.typeIndex],
        mode: state.modeIndex,
        random: state.random,
        tag: state.tag,
      );

      if (newMedia.isNotEmpty) {
        state = state.replace(
          mediaItems: mergeMediaItems(state.mediaItems, newMedia),
        );
      }
    } catch (e) {
      print('Fehler beim Laden der Medien: $e');
    } finally {
      state = state.replace(isLoading: false);
    }
  }

  void toggleMute() {
    state = state.replace(muted: !state.muted);
    _saveMutedState();
  }
}

final mediaProvider = StateNotifierProvider<MediaNotifier, MediaState>(
  (ref) => MediaNotifier(),
);
