using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MangaReader.Core.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml.Media.Imaging;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MangaReader.WinUI.ViewModels;

public partial class LibraryViewModel(MangaContext context) : ViewModelBase
{
    private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();

    private CancellationTokenSource? _cancellationTokenSource;

    private string? _keyword;

    public string? Keyword
    {
        get
        {
            return _keyword;
        }
        set
        {
            SetProperty(ref _keyword, value);
        }
    }

    private ObservableCollection<ObservableMangaItem> _mangaItems = [];

    public ObservableCollection<ObservableMangaItem> MangaItems
    {
        get
        {
            return _mangaItems;
        }
        set
        {
            SetProperty(ref _mangaItems, value);
        }
    }

    public ICommand SearchCommand => new AsyncRelayCommand(SearchAsync);
    //public ICommand ImportCommand => new AsyncRelayCommand(ImportAsync);

    public async Task SearchAsync()
    {
        //if (string.IsNullOrWhiteSpace(Keyword))
        //    return;

        _cancellationTokenSource?.Cancel();
        _cancellationTokenSource = new();

        ObservableMangaItem[] mangaItems = await GetMangaItemsAsync(_cancellationTokenSource.Token);

        _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
        {
            MangaItems = new(mangaItems);
        });

        //MangaItems = new(mangaItems);
    }

    public async Task<ObservableMangaItem[]> GetMangaItemsAsync(CancellationToken cancellationToken)
    {
        Manga[] mangas = await context.Mangas
            .Include(x => x.Titles)
            .Include(x => x.Descriptions)
            .Include(x => x.Genres).ThenInclude(x => x.Genre)
            //.Include(x => x.Sources)
            //.ThenInclude(x => x.Chapters)
            .ToArrayAsync(cancellationToken);

        List<ObservableMangaItem> mangaItems = [];

        foreach (Manga manga in mangas)
        {
            ObservableMangaItem mangaItem = new()
            {
                MangaId = manga.MangaId,
                Title = manga.Titles.OrderByDescending(title => title.IsPrimary).FirstOrDefault()?.Name,
                Description = manga.Descriptions.FirstOrDefault()?.Text,
                Genres = [.. manga.Genres.Select(x => x.Genre.Name)]
            };

            mangaItems.Add(mangaItem);
        }

        return [.. mangaItems];
    }
}

public partial class ObservableMangaItem : ObservableObject
{
    public int MangaId { get; init; }
    public string? Title { get; init; }
    public string? Description { get; init; }
    public string? Thumbnail { get; init; }
    public string[] Genres { get; init; } = [];

    private BitmapImage? _thumbnailBitmap;

    public BitmapImage? ThumbnailBitmap
    {
        get
        {
            return _thumbnailBitmap;
        }
        set
        {
            SetProperty(ref _thumbnailBitmap, value);
        }
    }
}