import 'package:flutter/material.dart';
import 'package:aves/model/db/local_media_db.dart';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/vaults/vaults.dart';
import 'album_sort.dart';

/// Controller che gestisce la lista degli album (basato su tabella `folders`)
class AlbumController extends ChangeNotifier {
  final LocalMediaDb localMediaDb;

  AlbumController({required this.localMediaDb});

  bool loading = true;

  // Lista completa degli album (AlbumRow)
  List<AlbumRow> _allAlbums = [];

  AlbumSortType _sortType = AlbumSortType.priorityThenName;

  // ============================================================
  // CARICAMENTO
  // ============================================================
  Future<void> load() async {
    loading = true;
    notifyListeners();

    // 1) Carica tutte le righe della tabella `folders`
    final rows = await localMediaDb.loadFolders();

    // 2) Nessun loadEntriesMap(): thumbEntry = null
    final list = <AlbumRow>[];
    final entriesMap = await localMediaDb.loadEntriesMap();

    for (final row in rows) {
      list.add(
        AlbumRow(
          path: row.path,
          displayName: row.displayName,
          albumType: row.albumType,
          priority: row.priority,
          totalSize: row.totalSize,
          fileCount: row.fileCount,
          isRemote: row.isRemote == 1,
          isVault: vaults.vaultDirectories.contains(row.path),
          hybridType: row.hybridType,
          hidden: row.hidden == 1,
          thumbEntry: row.thumbEntryId != null ? entriesMap[row.thumbEntryId] : null,
        ),
      );
    }

    // 3) Ordina
    _allAlbums = sortAlbums(list, _sortType);

    loading = false;
    notifyListeners();
  }

  Future<void> refresh() async => load();

  // ============================================================
  // SEZIONI: PINNED + NORMAL
  // ============================================================
  List<AlbumRow> get pinnedAlbums {
    final list = _allAlbums.where((a) => a.priority > 0 && !a.hidden).toList();
    list.sort((a, b) => a.priority.compareTo(b.priority));
    return list;
  }

  List<AlbumRow> get normalAlbums {
    final list = _allAlbums.where((a) => a.priority == 0 && !a.hidden).toList();
    list.sort((a, b) => a.displayName.toLowerCase().compareTo(b.displayName.toLowerCase()));
    return list;
  }

  // ============================================================
  // SORT
  // ============================================================
  void sortBy(AlbumSortType type) {
    _sortType = type;

    switch (type) {
      case AlbumSortType.priorityThenName:
        _allAlbums.sort((a, b) {
          final aPinned = a.priority > 0;
          final bPinned = b.priority > 0;

          if (aPinned && !bPinned) return -1;
          if (!aPinned && bPinned) return 1;

          if (aPinned && bPinned) {
            return a.priority.compareTo(b.priority);
          }

          return a.displayName.toLowerCase().compareTo(b.displayName.toLowerCase());
        });
        break;

      case AlbumSortType.nameAsc:
        _allAlbums.sort((a, b) => a.displayName.toLowerCase().compareTo(b.displayName.toLowerCase()));
        break;

      case AlbumSortType.nameDesc:
        _allAlbums.sort((a, b) => b.displayName.toLowerCase().compareTo(a.displayName.toLowerCase()));
        break;
    }

    notifyListeners();
  }

  // ============================================================
  // PIN / UNPIN
  // ============================================================
  Future<void> togglePin(AlbumRow album) async {
    final newPriority = album.priority > 0 ? 0 : _computeNewPinPriority();
    await localMediaDb.updateFolderPriority(album.path, newPriority);
    await load();
  }

  int _computeNewPinPriority() {
    final pinned = pinnedAlbums;
    if (pinned.isEmpty) return 1000;
    return pinned.first.priority + 1000;
  }

  // ============================================================
  // DRAG & DROP PINNED
  // ============================================================
  Future<void> reorderPinned(int oldIndex, int newIndex) async {
    final pinned = pinnedAlbums;

    if (newIndex > oldIndex) newIndex -= 1;

    final item = pinned.removeAt(oldIndex);
    pinned.insert(newIndex, item);

    for (int i = 0; i < pinned.length; i++) {
      final album = pinned[i];
      final newPriority = i + 1;

      if (album.priority != newPriority) {
        await localMediaDb.updateFolderPriority(album.path, newPriority);
      }
    }

    await load();
  }

  // ============================================================
  // NASCONDI / MOSTRA
  // ============================================================
  Future<void> toggleHidden(AlbumRow album) async {
    final newHidden = album.hidden ? 0 : 1;
    await localMediaDb.updateFolderHidden(album.path, newHidden);
    await load();
  }

  // ============================================================
  // RINOMINA
  // ============================================================
  Future<void> renameAlbum(AlbumRow album, String newName) async {
    await localMediaDb.updateFolderDisplayName(album.path, newName);
    await load();
  }

  // ============================================================
  // CAMBIA COVER
  // ============================================================
  Future<void> setCover(AlbumRow album, AvesEntry entry) async {
    await localMediaDb.updateFolderCover(album.path, entry.id);
    await load();
  }

  // ============================================================
  // ELIMINA ALBUM
  // ============================================================
  Future<void> deleteAlbum(AlbumRow album) async {
    await localMediaDb.deleteFolder(album.path);
    await load();
  }
}
