using Domain.Entities.EmailVerification.ValueObject;

namespace Domain.Entities.EmailVerification
{
    public class EmailVerifyToken
    {
        public int ID { get; private set; }

        public VerificationType Type { get; private set; }

        public string Email { get; private set; } = default!;

        public string Token { get; private set; } = default!;

        public bool IsVerified { get; private set; } = false;

        public DateTime Expiration { get; private set; }

        public string? Additional { get; private set; }

        public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;

        public AdditionalData? AdditionalData
        {
            get => Additional == null ? null : System.Text.Json.JsonSerializer.Deserialize<AdditionalData>(Additional);
            set => Additional = value == null ? null : System.Text.Json.JsonSerializer.Serialize(value);
        }

        private EmailVerifyToken() { }

        private EmailVerifyToken(VerificationType type, string email, string token, DateTime expiration, AdditionalData? additionalData)
        {
            if (string.IsNullOrWhiteSpace(email))
            {
                throw new ArgumentException("Email is required.", nameof(email));
            }

            if (email.Length > 60)
            {
                throw new ArgumentOutOfRangeException(nameof(email));
            }

            if (string.IsNullOrWhiteSpace(token))
            {
                throw new ArgumentException("Token is required.", nameof(token));
            }

            if (token.Length > 256)
            {
                throw new ArgumentOutOfRangeException(nameof(token));
            }

            Type = type;
            Email = email;
            Token = token;
            Expiration = expiration;
            AdditionalData = additionalData;
            CreatedAt = DateTime.UtcNow;
        }

        public static EmailVerifyToken Create(VerificationType type, string email, string token, DateTime expiration, AdditionalData? additionalData = null)
        {
            return new(type, email, token, expiration, additionalData);
        }

        public void MarkVerified()
        {
            IsVerified = true;
        }
    }
}