using MySqlConnector;
using SharpChat.Configuration;

namespace SharpChat.MariaDB;

public partial class MariaDBMessageStorage {
    public static string BuildConnString(Config config) {
        return BuildConnString(
            config.ReadValue("host", "localhost"),
            config.ReadValue("user", string.Empty),
            config.ReadValue("pass", string.Empty),
            config.ReadValue("db", "sharpchat")
        );
    }

    public static string BuildConnString(string? host, string? username, string? password, string? database) {
        return new MySqlConnectionStringBuilder {
            Server = host,
            UserID = username,
            Password = password,
            Database = database,
            OldGuids = false,
            TreatTinyAsBoolean = false,
            CharacterSet = "utf8mb4",
            SslMode = MySqlSslMode.None,
            ForceSynchronous = true,
            ConnectionTimeout = 5,
            DefaultCommandTimeout = 900, // fuck it, 15 minutes
        }.ToString();
    }

    private async Task<MySqlConnection> GetConnection() {
        MySqlConnection conn = new(ConnectionString);
        await conn.OpenAsync();
        return conn;
    }

    private async Task<int> RunCommand(string command, params MySqlParameter[] parameters) {
        try {
            using MySqlConnection conn = await GetConnection();
            using MySqlCommand cmd = conn.CreateCommand();
            if(parameters?.Length > 0)
                cmd.Parameters.AddRange(parameters);
            cmd.CommandText = command;
            return await cmd.ExecuteNonQueryAsync();
        } catch(MySqlException ex) {
            Logger.Write(ex);
        }

        return 0;
    }

    private async Task<MySqlDataReader?> RunQuery(string command, params MySqlParameter[] parameters) {
        try {
            MySqlConnection conn = await GetConnection();
            MySqlCommand cmd = conn.CreateCommand();
            if(parameters?.Length > 0)
                cmd.Parameters.AddRange(parameters);
            cmd.CommandText = command;
            return await cmd.ExecuteReaderAsync(System.Data.CommandBehavior.CloseConnection);
        } catch(MySqlException ex) {
            Logger.Write(ex);
        }

        return null;
    }

    private async Task<T> RunQueryValue<T>(string command, params MySqlParameter[] parameters)
        where T : struct {
        try {
            using MySqlConnection conn = await GetConnection();
            using MySqlCommand cmd = conn.CreateCommand();
            if(parameters?.Length > 0)
                cmd.Parameters.AddRange(parameters);
            cmd.CommandText = command;
            await cmd.PrepareAsync();

            object? raw = await cmd.ExecuteScalarAsync();
            if(raw is T value)
                return value;
        } catch(MySqlException ex) {
            Logger.Write(ex);
        }

        return default;
    }
}