using Autofac;
using Insight.Database;
using PlanTempus.Components.Accounts.Exceptions;
using PlanTempus.Core.Database;
using PlanTempus.Core.Database.ConnectionFactory;
using Shouldly;

namespace PlanTempus.X.TDD;

[TestClass]
public class PostgresTests : TestFixture
{
    private IDbConnectionFactory _connFactory;
    private IDatabaseOperations _databaseOperations;

    [TestInitialize]
    public void MyTestMethod()
    {
        _connFactory = Container.Resolve<IDbConnectionFactory>();
        _databaseOperations = Container.Resolve<IDatabaseOperations>();
    }

    [TestMethod]
    public void TestDefaultConnection()
    {
        //https://stackoverflow.com/questions/69169247/how-to-create-idbconnection-factory-using-autofac-for-dapper

        using (var conn = _connFactory.Create())
        {
            conn.ExecuteSql("SELECT 1 as p");
        }
    }

    [TestMethod]
    public async Task TestScopeConnectionWithLogging()
    {
        using var db = _databaseOperations.CreateScope(nameof(TestScopeConnectionWithLogging));
        try
        {
            var user = await db.Connection.QuerySqlAsync<string>(
                "SELECT tablename FROM pg_tables limit 5");
        }
        catch (Exception ex)
        {
            db.Error(ex);
            throw;
        }
    }

    [TestMethod]
    public async Task TestScopeConnectionWithErrorLogging()
    {
        using var db = _databaseOperations.CreateScope(nameof(TestScopeConnectionWithLogging));
        try
        {
            var user = await db.Connection.QuerySqlAsync<string>(
                "SELECT tablename FROM pg_tables limit 5");
        }
        catch (Exception ex)
        {
            db.Error(ex);
        }
    }

    [TestMethod]
    public async Task TestForUniqueAccountEmail()
    {
        using var db = _databaseOperations.CreateScope(nameof(TestForUniqueAccountEmail));
        try
        {
            var sql = @"INSERT INTO system.accounts(email, password_hash, security_stamp, email_confirmed, access_failed_count, lockout_enabled, is_active)
            VALUES(@Email, @PasswordHash, @SecurityStamp, @EmailConfirmed, @AccessFailedCount, @LockoutEnabled, @IsActive)
            RETURNING id, created_at, email, is_active";

            var parameters = new
            {
                Email =  $"{GetRandomWord()}@mars.com",
                PasswordHash = "MartianRover2025",
                SecurityStamp = "MarsOrBust",
                EmailConfirmed = true,
                AccessFailedCount = 0,
                LockoutEnabled = false,
                IsActive = true
            };

            var account = await db.Connection.QuerySqlAsync<dynamic>(sql, parameters);

            //EmailAlreadyRegistreredException
            //try insert, to test exception
            var ex = await Should.ThrowAsync<Npgsql.PostgresException>(async () =>
                await db.Connection.QuerySqlAsync<dynamic>(sql, parameters));
            ex.ConstraintName.ShouldBe("accounts_email_key");
        }
        catch (Exception ex)
        {
            db.Error(ex);

        }
    }

    [TestMethod]
    public async Task TestSimpleDatabaseOperation()
    {
        try
        {
            await _databaseOperations.ExecuteAsync(async connection =>
            {
                return await connection.QuerySqlAsync<string>(
                    "SELECT tablename FROM pg_tables limit 5");
            }, nameof(TestSimpleDatabaseOperation));
        }
        catch (Exception ex)
        {
            throw;
        }
    }

    [TestMethod]
    public void SetupPostgresql_LISTEN()
    {
        //this is not in use a the moment... kind of premature test to get my mind in to gear
        //var builder = new ConfigurationBuilder()
        //					.AddPostgresConfiguration(options =>
        //					{
        //						options.ConnectionString = "Host=192.168.1.57;Database=ptdb01;Username=postgres;Password=3911";
        //						options.Channel = "config_changes";
        //						options.ConfigurationQuery = @"select * from dev.app_configuration";
        //					});
    }
}