using System;
using Jellyfin.Server.Implementations;
using MediaBrowser.Common.Configuration;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Database.Providers.SqLite;
/// 
/// Configures jellyfin to use an SqLite database.
/// 
[JellyfinDatabaseProviderKey("Jellyfin-SqLite")]
public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
{
    private readonly IApplicationPaths _applicationPaths;
    private readonly ILogger _logger;
    /// 
    /// Initializes a new instance of the  class.
    /// 
    /// Service to construct the fallback when the old data path configuration is used.
    /// A logger.
    public SqliteDatabaseProvider(IApplicationPaths applicationPaths, ILogger logger)
    {
        _applicationPaths = applicationPaths;
        _logger = logger;
    }
    /// 
    public IDbContextFactory? DbContextFactory { get; set; }
    /// 
    public void Initialise(DbContextOptionsBuilder options)
    {
        options.UseSqlite(
            $"Filename={Path.Combine(_applicationPaths.DataPath, "jellyfin.db")};Pooling=false",
            sqLiteOptions => sqLiteOptions.MigrationsAssembly(GetType().Assembly));
    }
    /// 
    public async Task RunScheduledOptimisation(CancellationToken cancellationToken)
    {
        var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
        await using (context.ConfigureAwait(false))
        {
            if (context.Database.IsSqlite())
            {
                await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false);
                await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false);
                _logger.LogInformation("jellyfin.db optimized successfully!");
            }
            else
            {
                _logger.LogInformation("This database doesn't support optimization");
            }
        }
    }
    /// 
    public void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.SetDefaultDateTimeKind(DateTimeKind.Utc);
    }
    /// 
    public async ValueTask DisposeAsync()
    {
        // Run before disposing the application
        var context = await DbContextFactory!.CreateDbContextAsync().ConfigureAwait(false);
        await using (context.ConfigureAwait(false))
        {
            await context.Database.ExecuteSqlRawAsync("PRAGMA optimize").ConfigureAwait(false);
        }
        SqliteConnection.ClearAllPools();
    }
}