using BookReader.Models;
using BookReader.Services;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

namespace BookReader.ViewModels;

public partial class BookshelfViewModel : BaseViewModel
{
    private readonly IDatabaseService _databaseService;
    private readonly IBookParserService _bookParserService;
    private readonly ISettingsService _settingsService;

    public ObservableCollection<Book> Books { get; } = new();

    [ObservableProperty]
    private bool _isEmpty;

    public BookshelfViewModel(
        IDatabaseService databaseService,
        IBookParserService bookParserService,
        ISettingsService settingsService)
    {
        _databaseService = databaseService;
        _bookParserService = bookParserService;
        _settingsService = settingsService;
        Title = "My Library";
    }

    [RelayCommand]
    public async Task LoadBooksAsync()
    {
        if (IsBusy) return;
        IsBusy = true;

        try
        {
            var books = await _databaseService.GetAllBooksAsync();
            Books.Clear();
            foreach (var book in books)
            {
                Books.Add(book);
            }
            IsEmpty = Books.Count == 0;
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine($"Error loading books: {ex.Message}");
        }
        finally
        {
            IsBusy = false;
        }
    }

    [RelayCommand]
    public async Task AddBookFromFileAsync()
    {
        try
        {
            var customFileTypes = new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>>
            {
                { DevicePlatform.Android, new[] { "application/epub+zip", "application/x-fictionbook+xml", "application/octet-stream", "*/*" } }
            });

            var result = await FilePicker.Default.PickAsync(new PickOptions
            {
                PickerTitle = "Select a book",
                FileTypes = customFileTypes
            });

            if (result == null) return;

            var extension = Path.GetExtension(result.FileName).ToLowerInvariant();
            if (extension != ".epub" && extension != ".fb2")
            {
                await Shell.Current.DisplayAlert("Error", "Only EPUB and FB2 formats are supported.", "OK");
                return;
            }

            IsBusy = true;
            StatusMessage = "Adding book...";

            // Copy to temp if needed and parse
            string filePath;
            using var stream = await result.OpenReadAsync();
            var tempPath = Path.Combine(FileSystem.CacheDirectory, result.FileName);
            using (var fileStream = File.Create(tempPath))
            {
                await stream.CopyToAsync(fileStream);
            }
            filePath = tempPath;

            var book = await _bookParserService.ParseAndStoreBookAsync(filePath, result.FileName);
            Books.Insert(0, book);
            IsEmpty = false;

            // Clean temp
            try { File.Delete(tempPath); } catch { }
        }
        catch (Exception ex)
        {
            await Shell.Current.DisplayAlert("Error", $"Failed to add book: {ex.Message}", "OK");
        }
        finally
        {
            IsBusy = false;
            StatusMessage = string.Empty;
        }
    }

    [RelayCommand]
    public async Task DeleteBookAsync(Book book)
    {
        if (book == null) return;

        var confirm = await Shell.Current.DisplayAlert("Delete Book",
            $"Are you sure you want to delete \"{book.Title}\"?", "Delete", "Cancel");

        if (!confirm) return;

        try
        {
            await _databaseService.DeleteBookAsync(book);
            Books.Remove(book);
            IsEmpty = Books.Count == 0;
        }
        catch (Exception ex)
        {
            await Shell.Current.DisplayAlert("Error", $"Failed to delete book: {ex.Message}", "OK");
        }
    }

    [RelayCommand]
    public async Task OpenBookAsync(Book book)
    {
        if (book == null) return;

        var navigationParameter = new Dictionary<string, object>
        {
            { "Book", book }
        };

        await Shell.Current.GoToAsync("reader", navigationParameter);
    }

    [RelayCommand]
    public async Task OpenSettingsAsync()
    {
        await Shell.Current.GoToAsync("settings");
    }

    [RelayCommand]
    public async Task OpenCalibreLibraryAsync()
    {
        await Shell.Current.GoToAsync("calibre");
    }
}