namespace ChatService.Domain.AggregatesModel.UserAggregate;

using ChatService.Domain.SeedWork;

/// <summary>
/// EN: User's public key bundle for E2EE key exchange (X3DH protocol).
/// VI: Bundle public keys của user cho E2EE key exchange (X3DH protocol).
/// </summary>
/// <remarks>
/// EN: Contains only PUBLIC keys - private keys are stored client-side only.
/// VI: Chỉ chứa PUBLIC keys - private keys được lưu trữ ở client.
/// </remarks>
public class UserKeyBundle : ValueObject
{
    /// <summary>
    /// EN: Long-term identity public key (Curve25519).
    /// VI: Public key định danh lâu dài (Curve25519).
    /// </summary>
    public string IdentityPublicKey { get; private set; }

    /// <summary>
    /// EN: Signed pre-key (rotated periodically, e.g., every 30 days).
    /// VI: Signed pre-key (xoay vòng định kỳ, vd: mỗi 30 ngày).
    /// </summary>
    public string SignedPreKey { get; private set; }

    /// <summary>
    /// EN: Signature of the signed pre-key using identity private key.
    /// VI: Chữ ký của signed pre-key sử dụng identity private key.
    /// </summary>
    public string SignedPreKeySignature { get; private set; }

    /// <summary>
    /// EN: Timestamp when signed pre-key was generated.
    /// VI: Thời điểm signed pre-key được tạo.
    /// </summary>
    public DateTime SignedPreKeyTimestamp { get; private set; }

    protected UserKeyBundle()
    {
        // EN: Required by EF Core
        // VI: Yêu cầu bởi EF Core
        IdentityPublicKey = string.Empty;
        SignedPreKey = string.Empty;
        SignedPreKeySignature = string.Empty;
    }

    public UserKeyBundle(
        string identityPublicKey,
        string signedPreKey,
        string signedPreKeySignature,
        DateTime? signedPreKeyTimestamp = null)
    {
        if (string.IsNullOrWhiteSpace(identityPublicKey))
            throw new ArgumentException("Identity public key is required", nameof(identityPublicKey));
        if (string.IsNullOrWhiteSpace(signedPreKey))
            throw new ArgumentException("Signed pre-key is required", nameof(signedPreKey));
        if (string.IsNullOrWhiteSpace(signedPreKeySignature))
            throw new ArgumentException("Signed pre-key signature is required", nameof(signedPreKeySignature));

        IdentityPublicKey = identityPublicKey;
        SignedPreKey = signedPreKey;
        SignedPreKeySignature = signedPreKeySignature;
        SignedPreKeyTimestamp = signedPreKeyTimestamp ?? DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update signed pre-key (key rotation).
    /// VI: Cập nhật signed pre-key (xoay vòng key).
    /// </summary>
    public UserKeyBundle RotateSignedPreKey(string newSignedPreKey, string newSignature)
    {
        return new UserKeyBundle(
            IdentityPublicKey,
            newSignedPreKey,
            newSignature,
            DateTime.UtcNow);
    }

    /// <summary>
    /// EN: Check if signed pre-key needs rotation (older than 30 days).
    /// VI: Kiểm tra xem signed pre-key có cần xoay vòng không (cũ hơn 30 ngày).
    /// </summary>
    public bool NeedsRotation(int maxAgeDays = 30)
    {
        return (DateTime.UtcNow - SignedPreKeyTimestamp).TotalDays > maxAgeDays;
    }

    protected override IEnumerable<object> GetEqualityComponents()
    {
        yield return IdentityPublicKey;
        yield return SignedPreKey;
        yield return SignedPreKeySignature;
        yield return SignedPreKeyTimestamp;
    }
}
