using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using Workflow.Domain.Common;
using Workflow.Domain.Entities;

namespace Workflow.Infrastructure.Persistence;

public class WorkflowDbContext : DbContext
{
    public DbSet<WorkflowDefinition> WorkflowDefinitions => Set<WorkflowDefinition>();
    public DbSet<WorkflowNode> WorkflowNodes => Set<WorkflowNode>();
    public DbSet<WorkflowEdge> WorkflowEdges => Set<WorkflowEdge>();
    public DbSet<WorkflowInstance> WorkflowInstances => Set<WorkflowInstance>();
    public DbSet<WorkflowToken> WorkflowTokens => Set<WorkflowToken>();
    public DbSet<WorkflowTask> WorkflowTasks => Set<WorkflowTask>();
    public DbSet<FormDefinition> FormDefinitions => Set<FormDefinition>();
    public DbSet<FormDefinitionField> FormDefinitionFields => Set<FormDefinitionField>();
    public DbSet<FormData> FormData => Set<FormData>();

    public WorkflowDbContext(DbContextOptions<WorkflowDbContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(WorkflowDbContext).Assembly);

        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType))
            {
                modelBuilder.Entity(entityType.ClrType).HasQueryFilter(
                    CreateSoftDeleteFilter(entityType.ClrType));
            }
        }
    }

    private static LambdaExpression CreateSoftDeleteFilter(Type entityType)
    {
        var param = Expression.Parameter(entityType, "e");
        var isDeletedProp = Expression.Property(param, nameof(ISoftDelete.IsDeleted));
        var filter = Expression.Lambda(Expression.Not(isDeletedProp), param);
        return filter;
    }
}
