using System.Data.Common;
using System.Data.SQLite;
using NativeSQLiteConnection = System.Data.SQLite.SQLiteConnection;

namespace SharpChat.SQLite;

public class SQLiteConnection(NativeSQLiteConnection conn) : IDisposable {
    public NativeSQLiteConnection Connection { get; } = conn;

    public async Task<int> RunCommand(string command, params SQLiteParameter[] parameters) {
        using SQLiteCommand cmd = Connection.CreateCommand();
        cmd.Parameters.Clear();
        if(parameters?.Length > 0)
            cmd.Parameters.AddRange(parameters);
        cmd.CommandText = command;
        return await cmd.ExecuteNonQueryAsync();
    }

    public async Task<DbDataReader?> RunQuery(string command, params SQLiteParameter[] parameters) {
        using SQLiteCommand cmd = Connection.CreateCommand();
        cmd.Parameters.Clear();
        if(parameters?.Length > 0)
            cmd.Parameters.AddRange(parameters);
        cmd.CommandText = command;
        return await cmd.ExecuteReaderAsync();
    }

    public async Task<T> RunQueryValue<T>(string command, params SQLiteParameter[] parameters)
        where T : struct {
        using SQLiteCommand cmd = Connection.CreateCommand();
        cmd.Parameters.Clear();
        if(parameters?.Length > 0)
            cmd.Parameters.AddRange(parameters);
        cmd.CommandText = command;
        await cmd.PrepareAsync();

        object? raw = await cmd.ExecuteScalarAsync();
        return raw is T value ? value : default;
    }

    private bool disposed = false;

    ~SQLiteConnection() {
        DoDispose();
    }

    public void Dispose() {
        DoDispose();
        GC.SuppressFinalize(this);
    }

    private void DoDispose() {
        if(disposed)
            return;
        disposed = true;

        RunCommand("VACUUM").Wait();
        Connection.Dispose();
    }
}