using IamService.Domain.SeedWork;

namespace IamService.Domain.AggregatesModel.UserAggregate;

/// <summary>
/// EN: Address value object.
/// VI: Value object địa chỉ.
/// </summary>
public class Address : ValueObject
{
    /// <summary>
    /// EN: Street address (line 1).
    /// VI: Địa chỉ đường (dòng 1).
    /// </summary>
    public string Street { get; }

    /// <summary>
    /// EN: Additional address info (line 2).
    /// VI: Thông tin địa chỉ bổ sung (dòng 2).
    /// </summary>
    public string? Street2 { get; }

    /// <summary>
    /// EN: City name.
    /// VI: Tên thành phố.
    /// </summary>
    public string City { get; }

    /// <summary>
    /// EN: State or province.
    /// VI: Tỉnh/Thành phố.
    /// </summary>
    public string? State { get; }

    /// <summary>
    /// EN: Postal or ZIP code.
    /// VI: Mã bưu điện.
    /// </summary>
    public string? PostalCode { get; }

    /// <summary>
    /// EN: Country code (ISO 3166-1 alpha-2).
    /// VI: Mã quốc gia (ISO 3166-1 alpha-2).
    /// </summary>
    public string Country { get; }

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    private Address()
    {
        Street = string.Empty;
        City = string.Empty;
        Country = string.Empty;
    }

    /// <summary>
    /// EN: Create a new address.
    /// VI: Tạo địa chỉ mới.
    /// </summary>
    public Address(
        string street,
        string city,
        string country,
        string? street2 = null,
        string? state = null,
        string? postalCode = null)
    {
        if (string.IsNullOrWhiteSpace(street))
            throw new ArgumentException("Street cannot be empty", nameof(street));
        if (string.IsNullOrWhiteSpace(city))
            throw new ArgumentException("City cannot be empty", nameof(city));
        if (string.IsNullOrWhiteSpace(country))
            throw new ArgumentException("Country cannot be empty", nameof(country));

        Street = street.Trim();
        Street2 = street2?.Trim();
        City = city.Trim();
        State = state?.Trim();
        PostalCode = postalCode?.Trim();
        Country = country.Trim().ToUpperInvariant();
    }

    /// <summary>
    /// EN: Format address for display.
    /// VI: Định dạng địa chỉ để hiển thị.
    /// </summary>
    public string ToDisplayString()
    {
        var parts = new List<string> { Street };
        
        if (!string.IsNullOrEmpty(Street2))
            parts.Add(Street2);
        
        var cityLine = City;
        if (!string.IsNullOrEmpty(State))
            cityLine += $", {State}";
        if (!string.IsNullOrEmpty(PostalCode))
            cityLine += $" {PostalCode}";
        parts.Add(cityLine);
        
        parts.Add(Country);
        
        return string.Join("\n", parts);
    }

    /// <summary>
    /// EN: Format address as single line.
    /// VI: Định dạng địa chỉ thành một dòng.
    /// </summary>
    public string ToSingleLineString()
    {
        var parts = new List<string> { Street };
        
        if (!string.IsNullOrEmpty(Street2))
            parts.Add(Street2);
        
        parts.Add(City);
        
        if (!string.IsNullOrEmpty(State))
            parts.Add(State);
        if (!string.IsNullOrEmpty(PostalCode))
            parts.Add(PostalCode);
        
        parts.Add(Country);
        
        return string.Join(", ", parts);
    }

    protected override IEnumerable<object?> GetEqualityComponents()
    {
        yield return Street;
        yield return Street2;
        yield return City;
        yield return State;
        yield return PostalCode;
        yield return Country;
    }
}
