using System.Data;
using Npgsql;

namespace PlanTempus.Core.Database.ConnectionFactory
{

	public record ConnectionStringParameters(string User, string Pwd);

	public class PostgresConnectionFactory : IDbConnectionFactory, IAsyncDisposable
	{
		private readonly NpgsqlDataSource _baseDataSource;
		private readonly Action<NpgsqlDataSourceBuilder> _configureDataSource;
		private readonly Microsoft.Extensions.Logging.ILoggerFactory _loggerFactory; //this is not tested nor implemented, I just created it as an idea

		public PostgresConnectionFactory(
			string connectionString,
			Microsoft.Extensions.Logging.ILoggerFactory loggerFactory = null,
			Action<NpgsqlDataSourceBuilder> configureDataSource = null)
		{
			_loggerFactory = loggerFactory;
			_configureDataSource = configureDataSource ?? (builder => { });

			// Opret base data source med konfiguration
			var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
			ConfigureDataSourceBuilder(dataSourceBuilder);
			_baseDataSource = dataSourceBuilder.Build();
		}

		public IDbConnection Create()
		{
			return _baseDataSource.CreateConnection();
		}

		public IDbConnection Create(ConnectionStringParameters param)
		{
			var connectionStringBuilder = new NpgsqlConnectionStringBuilder(
				_baseDataSource.ConnectionString)
			{
				Username = param.User,
				Password = param.Pwd
			};

			var tempDataSourceBuilder = new NpgsqlDataSourceBuilder(
				connectionStringBuilder.ToString());

			ConfigureDataSourceBuilder(tempDataSourceBuilder);

			var tempDataSource = tempDataSourceBuilder.Build();
			return tempDataSource.CreateConnection();
		}

		private void ConfigureDataSourceBuilder(NpgsqlDataSourceBuilder builder)
		{
			if (_loggerFactory != null)
			{
				builder.UseLoggerFactory(_loggerFactory);
			}

			_configureDataSource?.Invoke(builder);
		}

		public async ValueTask DisposeAsync()
		{
			await _baseDataSource.DisposeAsync();
		}
	}
}
