using System;
using System.Linq.Expressions;
using System.Reflection;
using Kyoo.Models;
using Microsoft.EntityFrameworkCore;
using Npgsql;
namespace Kyoo.Postgresql
{
	/// 
	/// A postgresql implementation of .
	/// 
	public class PostgresContext : DatabaseContext
	{
		/// 
		/// The connection string to use.
		/// 
		private readonly string _connection;
		/// 
		/// Is this instance in debug mode?
		/// 
		private readonly bool _debugMode;
		/// 
		/// Should the configure step be skipped? This is used when the database is created via DbContextOptions.
		/// 
		private readonly bool _skipConfigure;
		
		/// 
		/// A basic constructor that set default values (query tracker behaviors, mapping enums...)
		/// 
		public PostgresContext()
		{
			NpgsqlConnection.GlobalTypeMapper.MapEnum();
			NpgsqlConnection.GlobalTypeMapper.MapEnum();
			NpgsqlConnection.GlobalTypeMapper.MapEnum();
		}
		/// 
		/// Create a new  using specific options
		/// 
		/// The options to use.
		public PostgresContext(DbContextOptions options)
			: base(options)
		{
			NpgsqlConnection.GlobalTypeMapper.MapEnum();
			NpgsqlConnection.GlobalTypeMapper.MapEnum();
			NpgsqlConnection.GlobalTypeMapper.MapEnum();
			_skipConfigure = true;
		}
		/// 
		/// A basic constructor that set default values (query tracker behaviors, mapping enums...)
		/// 
		/// The connection string to use
		/// Is this instance in debug mode?
		public PostgresContext(string connection, bool debugMode)
		{
			_connection = connection;
			_debugMode = debugMode;
		}
		/// 
		/// Set connection information for this database context
		/// 
		/// An option builder to fill.
		protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
		{
			if (!_skipConfigure)
			{
				if (_connection != null)
					optionsBuilder.UseNpgsql(_connection);
				else
					optionsBuilder.UseNpgsql();
				if (_debugMode)
					optionsBuilder.EnableDetailedErrors().EnableSensitiveDataLogging();
			}
			base.OnConfiguring(optionsBuilder);
		}
		/// 
		/// Set database parameters to support every types of Kyoo.
		/// 
		/// The database's model builder.
		protected override void OnModelCreating(ModelBuilder modelBuilder)
		{
			modelBuilder.HasPostgresEnum();
			modelBuilder.HasPostgresEnum();
			modelBuilder.HasPostgresEnum();
			modelBuilder.Entity()
				.Property(x => x.ExtraData)
				.HasColumnType("jsonb");
			
			base.OnModelCreating(modelBuilder);
		}
		/// 
		protected override bool IsDuplicateException(Exception ex)
		{
			return ex.InnerException is PostgresException {SqlState: PostgresErrorCodes.UniqueViolation};
		}
		/// 
		public override Expression> Like(Expression> query, string format)
		{
			MethodInfo iLike = MethodOfUtils.MethodOf(EF.Functions.ILike);
			MethodCallExpression call = Expression.Call(iLike, query.Body, Expression.Constant(format));
			return Expression.Lambda>(call, query.Parameters);
		}
	}
}