using MiningService.Domain.Events;
using MiningService.Domain.Exceptions;
using MiningService.Domain.SeedWork;

namespace MiningService.Domain.AggregatesModel.CircleAggregate;

/// <summary>
/// EN: Security Circle Aggregate Root - trusted group for mining bonus.
/// VI: Security Circle Aggregate Root - nhóm tin cậy cho thưởng đào.
/// </summary>
public class Circle : Entity, IAggregateRoot
{
    private readonly List<CircleMember> _members = new();
    
    private const int MinMembers = 3;
    private const int MaxMembers = 5;
    private const decimal ValidCircleBonus = 0.25m; // 25%

    #region Properties

    /// <summary>EN: Circle owner (creator) / VI: Chủ vòng tròn (người tạo)</summary>
    public Guid OwnerId { get; private set; }

    /// <summary>EN: Circle name / VI: Tên vòng tròn</summary>
    public string Name { get; private set; } = string.Empty;

    /// <summary>EN: Trust score (0-100) / VI: Điểm tin cậy (0-100)</summary>
    public decimal TrustScore { get; private set; }

    /// <summary>EN: Bonus multiplier for valid circle / VI: Hệ số thưởng cho vòng tròn hợp lệ</summary>
    public decimal BonusMultiplier { get; private set; }

    /// <summary>EN: Circle status / VI: Trạng thái vòng tròn</summary>
    public CircleStatus Status { get; private set; }

    /// <summary>EN: When circle was created / VI: Khi vòng tròn được tạo</summary>
    public DateTime CreatedAt { get; private set; }

    /// <summary>EN: Last update time / VI: Thời gian cập nhật cuối</summary>
    public DateTime UpdatedAt { get; private set; }

    /// <summary>EN: Circle members / VI: Các thành viên vòng tròn</summary>
    public IReadOnlyCollection<CircleMember> Members => _members.AsReadOnly();

    /// <summary>EN: Active member count / VI: Số thành viên hoạt động</summary>
    public int ActiveMemberCount => _members.Count(m => m.IsActive);

    /// <summary>EN: Is circle valid for bonus / VI: Vòng tròn có hợp lệ cho thưởng không</summary>
    public bool IsValid => Status == CircleStatus.Active && ActiveMemberCount >= MinMembers;

    #endregion

    // EF Core
    protected Circle() { }

    #region Factory

    /// <summary>
    /// EN: Create a new security circle.
    /// VI: Tạo vòng tròn an toàn mới.
    /// </summary>
    public static Circle Create(Guid ownerId, string name)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new CircleDomainException("Circle name is required");

        var circle = new Circle
        {
            Id = Guid.NewGuid(),
            OwnerId = ownerId,
            Name = name.Trim(),
            TrustScore = 0,
            BonusMultiplier = 0,
            Status = CircleStatus.Incomplete,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow
        };

        // Add owner as first member
        var ownerMember = CircleMember.Create(circle.Id, ownerId);
        circle._members.Add(ownerMember);

        return circle;
    }

    #endregion

    #region Member Management

    /// <summary>
    /// EN: Add member to circle.
    /// VI: Thêm thành viên vào vòng tròn.
    /// </summary>
    public void AddMember(Guid minerId)
    {
        if (Status == CircleStatus.Disbanded)
            throw new CircleDomainException("Cannot add member to disbanded circle");

        if (ActiveMemberCount >= MaxMembers)
            throw new CircleDomainException($"Circle cannot have more than {MaxMembers} members");

        if (_members.Any(m => m.MinerId == minerId))
            throw new CircleDomainException("Miner is already a member of this circle");

        var member = CircleMember.Create(Id, minerId);
        _members.Add(member);

        RecalculateStatus();
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Remove member from circle.
    /// VI: Xóa thành viên khỏi vòng tròn.
    /// </summary>
    public void RemoveMember(Guid minerId)
    {
        if (minerId == OwnerId)
            throw new CircleDomainException("Cannot remove circle owner");

        var member = _members.FirstOrDefault(m => m.MinerId == minerId);
        if (member == null)
            throw new CircleDomainException("Miner is not a member of this circle");

        member.Deactivate();
        RecalculateStatus();
        UpdatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Disband the circle.
    /// VI: Giải tán vòng tròn.
    /// </summary>
    public void Disband()
    {
        Status = CircleStatus.Disbanded;
        BonusMultiplier = 0;
        
        foreach (var member in _members)
            member.Deactivate();

        UpdatedAt = DateTime.UtcNow;
    }

    #endregion

    #region Private Helpers

    private void RecalculateStatus()
    {
        var wasActive = Status == CircleStatus.Active;

        if (ActiveMemberCount >= MinMembers)
        {
            Status = CircleStatus.Active;
            BonusMultiplier = ValidCircleBonus;
            CalculateTrustScore();

            if (!wasActive)
            {
                AddDomainEvent(new CircleCompletedDomainEvent(Id, OwnerId, ActiveMemberCount));
            }
        }
        else
        {
            Status = CircleStatus.Incomplete;
            BonusMultiplier = 0;
            TrustScore = 0;
        }
    }

    private void CalculateTrustScore()
    {
        // Simple trust score: based on member count and activity
        // Can be enhanced with more factors (member verify status, activity, etc.)
        TrustScore = ActiveMemberCount switch
        {
            3 => 60,
            4 => 80,
            5 => 100,
            _ => 0
        };
    }

    #endregion
}
