using BookReader.Models;
using SQLite;

namespace BookReader.Services;

public class DatabaseService : IDatabaseService
{
    private SQLiteAsyncConnection? _database;
    private readonly string _dbPath;

    public DatabaseService()
    {
        _dbPath = Path.Combine(FileSystem.AppDataDirectory, "bookreader.db3");
    }

    public async Task InitializeAsync()
    {
        if (_database != null) return;

        _database = new SQLiteAsyncConnection(_dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);

        await _database.CreateTableAsync<Book>();
        await _database.CreateTableAsync<AppSettings>();
        await _database.CreateTableAsync<ReadingProgress>();
    }

    private async Task EnsureInitializedAsync()
    {
        if (_database == null)
            await InitializeAsync();
    }

    // Books
    public async Task<List<Book>> GetAllBooksAsync()
    {
        await EnsureInitializedAsync();
        return await _database!.Table<Book>().OrderByDescending(b => b.LastRead).ToListAsync();
    }

    public async Task<Book?> GetBookByIdAsync(int id)
    {
        await EnsureInitializedAsync();
        return await _database!.Table<Book>().Where(b => b.Id == id).FirstOrDefaultAsync();
    }

    public async Task<int> SaveBookAsync(Book book)
    {
        await EnsureInitializedAsync();
        if (book.Id != 0)
            return await _database!.UpdateAsync(book);
        return await _database!.InsertAsync(book);
    }

    public async Task<int> UpdateBookAsync(Book book)
    {
        await EnsureInitializedAsync();
        return await _database!.UpdateAsync(book);
    }

    public async Task<int> DeleteBookAsync(Book book)
    {
        await EnsureInitializedAsync();

        // Delete associated file
        if (File.Exists(book.FilePath))
        {
            try { File.Delete(book.FilePath); } catch { }
        }

        // Delete progress records
        await _database!.Table<ReadingProgress>().DeleteAsync(p => p.BookId == book.Id);

        return await _database!.DeleteAsync(book);
    }

    // Settings
    public async Task<string?> GetSettingAsync(string key)
    {
        await EnsureInitializedAsync();
        var setting = await _database!.Table<AppSettings>().Where(s => s.Key == key).FirstOrDefaultAsync();
        return setting?.Value;
    }

    public async Task SetSettingAsync(string key, string value)
    {
        await EnsureInitializedAsync();
        var existing = await _database!.Table<AppSettings>().Where(s => s.Key == key).FirstOrDefaultAsync();
        if (existing != null)
        {
            existing.Value = value;
            await _database.UpdateAsync(existing);
        }
        else
        {
            await _database.InsertAsync(new AppSettings { Key = key, Value = value });
        }
    }

    public async Task<Dictionary<string, string>> GetAllSettingsAsync()
    {
        await EnsureInitializedAsync();
        var settings = await _database!.Table<AppSettings>().ToListAsync();
        return settings.ToDictionary(s => s.Key, s => s.Value);
    }

    // Reading Progress
    public async Task SaveProgressAsync(ReadingProgress progress)
    {
        await EnsureInitializedAsync();
        progress.Timestamp = DateTime.UtcNow;
        await _database!.InsertAsync(progress);
    }

    public async Task<ReadingProgress?> GetLatestProgressAsync(int bookId)
    {
        await EnsureInitializedAsync();
        return await _database!.Table<ReadingProgress>()
            .Where(p => p.BookId == bookId)
            .OrderByDescending(p => p.Timestamp)
            .FirstOrDefaultAsync();
    }
}