namespace MissionService.Domain.AggregatesModel.CheckInAggregate;

using MissionService.Domain.SeedWork;

/// <summary>
/// EN: Configuration for streak bonuses - Value Object
/// VI: Cấu hình thưởng streak - Value Object
/// </summary>
public class StreakBonusConfig : ValueObject
{
    /// <summary>EN: Base daily points / VI: Điểm cơ bản hàng ngày</summary>
    public decimal BasePoints { get; private set; }
    
    /// <summary>EN: Streak bonus tiers / VI: Các cấp thưởng streak</summary>
    private readonly List<StreakTier> _tiers;
    public IReadOnlyList<StreakTier> Tiers => _tiers.AsReadOnly();
    
    // EF Core constructor
    protected StreakBonusConfig()
    {
        _tiers = new List<StreakTier>();
    }
    
    private StreakBonusConfig(decimal basePoints, List<StreakTier> tiers)
    {
        BasePoints = basePoints;
        _tiers = tiers;
    }
    
    /// <summary>
    /// EN: Create default streak bonus config / VI: Tạo cấu hình thưởng streak mặc định
    /// </summary>
    public static StreakBonusConfig Default()
    {
        return new StreakBonusConfig(2m, new List<StreakTier>
        {
            // Days 1-6: 2 MP daily, no milestone
            new(1, 6, 2m, 0m),
            // Day 7: 3 MP daily + 20 MP milestone
            new(7, 7, 3m, 20m),
            // Days 8-13: 3 MP daily
            new(8, 13, 3m, 0m),
            // Day 14: 4 MP daily + 35 MP milestone
            new(14, 14, 4m, 35m),
            // Days 15-20: 4 MP daily
            new(15, 20, 4m, 0m),
            // Day 21: 5 MP daily + 50 MP milestone
            new(21, 21, 5m, 50m),
            // Days 22-29: 5 MP daily
            new(22, 29, 5m, 0m),
            // Day 30+: 10 MP daily + 100 MP milestone
            new(30, 999, 10m, 100m)
        });
    }
    
    /// <summary>
    /// EN: Create custom streak bonus config / VI: Tạo cấu hình thưởng streak tùy chỉnh
    /// </summary>
    public static StreakBonusConfig Create(decimal basePoints, List<StreakTier> tiers)
    {
        if (basePoints < 0)
            throw new ArgumentException("Base points cannot be negative");
        
        return new StreakBonusConfig(basePoints, tiers);
    }
    
    /// <summary>
    /// EN: Calculate reward for current streak day / VI: Tính thưởng cho ngày streak hiện tại
    /// </summary>
    public (decimal DailyPoints, decimal StreakBonus, decimal MilestoneBonus, bool IsMilestone) CalculateReward(int streakDay)
    {
        var tier = _tiers.FirstOrDefault(t => streakDay >= t.MinDays && streakDay <= t.MaxDays);
        
        if (tier == null)
        {
            // EN: Fallback to base points / VI: Dự phòng với điểm cơ bản
            return (BasePoints, 0m, 0m, false);
        }
        
        var isMilestone = tier.MilestoneBonus > 0;
        var streakBonus = tier.DailyPoints - BasePoints; // EN: Extra from tier / VI: Thêm từ cấp
        
        return (tier.DailyPoints, streakBonus > 0 ? streakBonus : 0, tier.MilestoneBonus, isMilestone);
    }
    
    protected override IEnumerable<object?> GetEqualityComponents()
    {
        yield return BasePoints;
        foreach (var tier in _tiers)
        {
            yield return tier;
        }
    }
}

/// <summary>
/// EN: Streak tier configuration / VI: Cấu hình cấp streak
/// </summary>
public record StreakTier(
    int MinDays,
    int MaxDays,
    decimal DailyPoints,
    decimal MilestoneBonus);
