using System.Reflection;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Entities.Payment;

using CMSMicroservice.Domain.Entities.Order;
using CMSMicroservice.Domain.Entities.DiscountShop;
using CMSMicroservice.Infrastructure.Persistence.Interceptors;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace CMSMicroservice.Infrastructure.Persistence;

public class ApplicationDbContext :  DbContext, IApplicationDbContext
{
    private readonly IMediator _mediator;
    private readonly AuditableEntitySaveChangesInterceptor _auditableEntitySaveChangesInterceptor;

    public ApplicationDbContext(
        DbContextOptions<ApplicationDbContext> options,
        IMediator mediator,
        AuditableEntitySaveChangesInterceptor auditableEntitySaveChangesInterceptor) 
        : base(options)
    {
        _mediator = mediator;
        _auditableEntitySaveChangesInterceptor = auditableEntitySaveChangesInterceptor;
    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
        builder.HasDefaultSchema("CMS");
        
        // Ignore MediatR notification types
        builder.Ignore<CMSMicroservice.Domain.Common.BaseEvent>();
        
        base.OnModelCreating(builder);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.AddInterceptors(_auditableEntitySaveChangesInterceptor);
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        await _mediator.DispatchDomainEvents(this);

        return await base.SaveChangesAsync(cancellationToken);
    }
    public DbSet<UserAddress> UserAddresses => Set<UserAddress>();
    public DbSet<Package> Packages => Set<Package>();
    public DbSet<Role> Roles => Set<Role>();
    public DbSet<Category> Categories => Set<Category>();
    public DbSet<UserRole> UserRoles => Set<UserRole>();
    public DbSet<UserCart> UserCarts => Set<UserCart>();
    public DbSet<ProductGallery> ProductGalleries => Set<ProductGallery>();
    public DbSet<FactorDetails> FactorDetails => Set<FactorDetails>();
    public DbSet<Product> Products => Set<Product>();
    public DbSet<ProductImage> ProductImages => Set<ProductImage>();
    public DbSet<User> Users => Set<User>();
    public DbSet<OtpToken> OtpTokens => Set<OtpToken>();
    public DbSet<Contract> Contracts => Set<Contract>();
    public DbSet<UserContract> UserContracts => Set<UserContract>();
    public DbSet<Tag> Tags => Set<Tag>();
    public DbSet<ProductCategory> ProductCategories => Set<ProductCategory>();
    public DbSet<ProductTag> ProductTags => Set<ProductTag>();
    public DbSet<Transaction> Transactions => Set<Transaction>();
    public DbSet<UserOrder> UserOrders => Set<UserOrder>();
    public DbSet<OrderVAT> OrderVATs => Set<OrderVAT>();
    public DbSet<UserPackagePurchase> UserPackagePurchases => Set<UserPackagePurchase>();
    public DbSet<UserWallet> UserWallets => Set<UserWallet>();
    public DbSet<UserWalletChangeLog> UserWalletChangeLogs => Set<UserWalletChangeLog>();
    public DbSet<DayaLoanContract> DayaLoanContracts => Set<DayaLoanContract>();
    
    // Payment
    public DbSet<ManualPayment> ManualPayments => Set<ManualPayment>();
    
    // Message
    public DbSet<PublicMessage> PublicMessages => Set<PublicMessage>();
    
    // ============= Network Club System DbSets =============
    
    // Configuration
    public DbSet<SystemConfiguration> SystemConfigurations => Set<SystemConfiguration>();
    public DbSet<SystemConfigurationHistory> SystemConfigurationHistories => Set<SystemConfigurationHistory>();
    
    // Club Management
    public DbSet<ClubMembership> ClubMemberships => Set<ClubMembership>();
    public DbSet<ClubFeature> ClubFeatures => Set<ClubFeature>();
    public DbSet<UserClubFeature> UserClubFeatures => Set<UserClubFeature>();
    public DbSet<ClubMembershipHistory> ClubMembershipHistories => Set<ClubMembershipHistory>();
    
    // Network
    public DbSet<NetworkWeeklyBalance> NetworkWeeklyBalances => Set<NetworkWeeklyBalance>();
    public DbSet<NetworkMembershipHistory> NetworkMembershipHistories => Set<NetworkMembershipHistory>();
    
    // Commission
    public DbSet<WeeklyCommissionPool> WeeklyCommissionPools => Set<WeeklyCommissionPool>();
    public DbSet<UserCommissionPayout> UserCommissionPayouts => Set<UserCommissionPayout>();
    public DbSet<CommissionPayoutHistory> CommissionPayoutHistories => Set<CommissionPayoutHistory>();
    public DbSet<WorkerExecutionLog> WorkerExecutionLogs => Set<WorkerExecutionLog>();
    
    // ============= Discount Shop DbSets =============
    public DbSet<DiscountProduct> DiscountProducts => Set<DiscountProduct>();
    public DbSet<DiscountCategory> DiscountCategories => Set<DiscountCategory>();
    public DbSet<DiscountProductCategory> DiscountProductCategories => Set<DiscountProductCategory>();
    public DbSet<DiscountShoppingCart> DiscountShoppingCarts => Set<DiscountShoppingCart>();
    public DbSet<DiscountOrder> DiscountOrders => Set<DiscountOrder>();
    public DbSet<DiscountOrderDetail> DiscountOrderDetails => Set<DiscountOrderDetail>();
}
