using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MiningService.Domain.AggregatesModel.MinerAggregate;

namespace MiningService.Infrastructure.EntityConfigurations;

/// <summary>
/// EN: EF Core configuration for Miner aggregate.
/// VI: Cấu hình EF Core cho Miner aggregate.
/// </summary>
public class MinerEntityTypeConfiguration : IEntityTypeConfiguration<Miner>
{
    public void Configure(EntityTypeBuilder<Miner> builder)
    {
        builder.ToTable("Miners");
        
        builder.HasKey(m => m.Id);
        
        builder.Property(m => m.UserId)
            .IsRequired();
        
        builder.HasIndex(m => m.UserId)
            .IsUnique()
            .HasDatabaseName("IX_Miners_UserId");
        
        builder.Property(m => m.Role)
            .HasConversion<string>()
            .HasMaxLength(20);
        
        builder.Property(m => m.TotalMinedPoints)
            .HasPrecision(18, 4);
        
        builder.Property(m => m.ReferralCode)
            .HasMaxLength(10);
        
        builder.HasIndex(m => m.ReferralCode)
            .IsUnique()
            .HasDatabaseName("IX_Miners_ReferralCode");
        
        builder.Property(m => m.Status)
            .HasConversion<string>()
            .HasMaxLength(20);
        
        // MiningRate as owned type (value object)
        builder.OwnsOne(m => m.CurrentRate, rate =>
        {
            rate.Property(r => r.BaseRate).HasPrecision(18, 4);
            rate.Property(r => r.RoleBonus).HasPrecision(5, 4);
            rate.Property(r => r.CircleBonus).HasPrecision(5, 4);
            rate.Property(r => r.ReferralBonus).HasPrecision(5, 4);
            rate.Property(r => r.StreakBonus).HasPrecision(5, 4);
        });
        
        // MiningStreak as owned type (value object)
        builder.OwnsOne(m => m.Streak, streak =>
        {
            streak.Property(s => s.CurrentStreak);
            streak.Property(s => s.LongestStreak);
            streak.Property(s => s.LastMiningDate);
            streak.Property(s => s.FreezeTokens);
            streak.Property(s => s.IsGracePeriod);
        });
        
        // ActiveSession as owned type (nullable)
        builder.OwnsOne(m => m.ActiveSession, session =>
        {
            session.Property(s => s.SessionId);
            session.Property(s => s.StartTime);
            session.Property(s => s.EndTime);
            session.Property(s => s.HourlyRate).HasPrecision(18, 4);
            session.Property(s => s.Status).HasConversion<string>().HasMaxLength(20);
            session.Property(s => s.AccumulatedPoints).HasPrecision(18, 4);
        });
        
        // RowVersion for concurrency
        builder.Property(m => m.RowVersion)
            .IsRowVersion();
        
        // Navigation to MiningHistories
        builder.HasMany(m => m.MiningHistories)
            .WithOne()
            .HasForeignKey(h => h.MinerId)
            .OnDelete(DeleteBehavior.Cascade);
        
        builder.Ignore(m => m.DomainEvents);
    }
}

/// <summary>
/// EN: EF Core configuration for MiningHistory.
/// VI: Cấu hình EF Core cho MiningHistory.
/// </summary>
public class MiningHistoryEntityTypeConfiguration : IEntityTypeConfiguration<MiningHistory>
{
    public void Configure(EntityTypeBuilder<MiningHistory> builder)
    {
        builder.ToTable("MiningHistories");
        
        builder.HasKey(h => h.Id);
        
        builder.Property(h => h.PointsEarned)
            .HasPrecision(18, 4);
        
        builder.Property(h => h.Source)
            .HasMaxLength(50);
        
        builder.Property(h => h.HourlyRateSnapshot)
            .HasPrecision(18, 4);
        
        builder.HasIndex(h => new { h.MinerId, h.EarnedAt })
            .HasDatabaseName("IX_MiningHistories_MinerId_EarnedAt");
        
        builder.Ignore(h => h.DomainEvents);
    }
}
