package com.social.media.domain.shared.valueobjects;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Objects;
import java.util.regex.Pattern;

/**
 * Value object representing an email address.
 * 
 * Ensures email format validation and immutability.
 * 
 * @author Social Media Manager Team
 * @since 2.0.0
 */
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Email {
    
    private static final Pattern EMAIL_PATTERN = Pattern.compile(
        "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@" +
        "(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"
    );
    
    @Column(name = "email", nullable = false, length = 255)
    private String value;
    
    private Email(String value) {
        this.value = Objects.requireNonNull(value, "Email cannot be null").toLowerCase().trim();
        validate();
    }
    
    /**
     * Create an Email from a string value
     */
    public static Email of(String value) {
        return new Email(value);
    }
    
    /**
     * Validate email format
     */
    private void validate() {
        if (value.isEmpty()) {
            throw new IllegalArgumentException("Email cannot be empty");
        }
        
        if (value.length() > 255) {
            throw new IllegalArgumentException("Email cannot exceed 255 characters");
        }
        
        if (!EMAIL_PATTERN.matcher(value).matches()) {
            throw new IllegalArgumentException("Invalid email format: " + value);
        }
    }
    
    /**
     * Get domain part of email
     */
    public String getDomain() {
        return value.substring(value.indexOf('@') + 1);
    }
    
    /**
     * Get local part of email (before @)
     */
    public String getLocalPart() {
        return value.substring(0, value.indexOf('@'));
    }
    
    /**
     * Get the email value
     */
    public String getValue() {
        return value;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Email email = (Email) obj;
        return Objects.equals(value, email.value);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(value);
    }
    
    @Override
    public String toString() {
        return value;
    }
}
