using MembershipService.Domain.SeedWork;

namespace MembershipService.Domain.AggregatesModel.ExperienceAggregate;

/// <summary>
/// EN: Experience transaction entity - tracks EXP history and source.
/// VI: Experience transaction entity - theo dõi lịch sử và nguồn gốc EXP.
/// </summary>
/// <remarks>
/// EN: Every time a member receives EXP, a transaction is created for audit trail.
/// This enables analytics on where EXP comes from and member engagement patterns.
/// VI: Mỗi lần member nhận EXP, một transaction được tạo để audit.
/// Điều này cho phép phân tích nguồn gốc EXP và patterns tương tác của member.
/// </remarks>
public class ExperienceTransaction : Entity
{
    private Guid _memberId;
    private int _points;
    private int _sourceId;
    private ExperienceSource _source = null!;
    private string? _referenceId;
    private string? _metadata; // JSON
    private int _levelAtTime;
    private DateTime _createdAt;

    /// <summary>
    /// EN: Member ID who received the EXP.
    /// VI: ID của member nhận EXP.
    /// </summary>
    public Guid MemberId => _memberId;

    /// <summary>
    /// EN: Amount of EXP points earned.
    /// VI: Số điểm EXP kiếm được.
    /// </summary>
    public int Points => _points;

    /// <summary>
    /// EN: Experience source ID (for EF Core mapping).
    /// VI: ID nguồn EXP (cho EF Core mapping).
    /// </summary>
    public int SourceId => _sourceId;

    /// <summary>
    /// EN: Experience source.
    /// VI: Nguồn EXP.
    /// </summary>
    public ExperienceSource Source => _source;

    /// <summary>
    /// EN: Reference ID (Order ID, Referral Code, etc.).
    /// VI: ID tham chiếu (Order ID, Referral Code, etc.).
    /// </summary>
    public string? ReferenceId => _referenceId;

    /// <summary>
    /// EN: Additional metadata as JSON string.
    /// VI: Metadata bổ sung dạng chuỗi JSON.
    /// </summary>
    public string? Metadata => _metadata;

    /// <summary>
    /// EN: Member's level when this EXP was earned.
    /// VI: Level của member khi nhận EXP này.
    /// </summary>
    public int LevelAtTime => _levelAtTime;

    /// <summary>
    /// EN: Creation timestamp.
    /// VI: Thời gian tạo.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected ExperienceTransaction()
    {
    }

    /// <summary>
    /// EN: Create new experience transaction.
    /// VI: Tạo experience transaction mới.
    /// </summary>
    /// <param name="memberId">Member ID / ID của member</param>
    /// <param name="points">EXP points / Số điểm EXP</param>
    /// <param name="source">Experience source / Nguồn EXP</param>
    /// <param name="levelAtTime">Member's current level / Level hiện tại của member</param>
    /// <param name="referenceId">Reference ID (optional) / ID tham chiếu (tùy chọn)</param>
    /// <param name="metadata">Metadata JSON (optional) / Metadata JSON (tùy chọn)</param>
    public ExperienceTransaction(
        Guid memberId,
        int points,
        ExperienceSource source,
        int levelAtTime,
        string? referenceId = null,
        string? metadata = null)
    {
        if (memberId == Guid.Empty)
            throw new ArgumentException("Member ID cannot be empty", nameof(memberId));
        if (points <= 0)
            throw new ArgumentException("Points must be positive", nameof(points));
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        if (levelAtTime < 1)
            throw new ArgumentException("Level at time must be at least 1", nameof(levelAtTime));

        Id = Guid.NewGuid();
        _memberId = memberId;
        _points = points;
        _sourceId = source.Id;
        _source = source;
        _levelAtTime = levelAtTime;
        _referenceId = referenceId;
        _metadata = metadata;
        _createdAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Set experience source (for EF Core loading).
    /// VI: Set experience source (cho EF Core loading).
    /// </summary>
    public void SetSource(ExperienceSource source)
    {
        _source = source;
    }
}
