// EN: Common value objects for Shop aggregate.
// VI: Các value objects chung cho Shop aggregate.

namespace MerchantService.Domain.AggregatesModel.ShopAggregate;

/// <summary>
/// EN: Contact information value object.
/// VI: Value object thông tin liên hệ.
/// </summary>
public record ContactInfo
{
    /// <summary>
    /// EN: Phone number.
    /// VI: Số điện thoại.
    /// </summary>
    public string Phone { get; init; } = string.Empty;
    
    /// <summary>
    /// EN: Email address.
    /// VI: Địa chỉ email.
    /// </summary>
    public string? Email { get; init; }
    
    /// <summary>
    /// EN: Website URL.
    /// VI: URL website.
    /// </summary>
    public string? Website { get; init; }
    
    /// <summary>
    /// EN: Empty contact info.
    /// VI: Thông tin liên hệ rỗng.
    /// </summary>
    public static ContactInfo Empty => new();
}

/// <summary>
/// EN: Physical address value object.
/// VI: Value object địa chỉ vật lý.
/// </summary>
public record Address
{
    /// <summary>
    /// EN: Street address.
    /// VI: Địa chỉ đường phố.
    /// </summary>
    public string Street { get; init; } = string.Empty;
    
    /// <summary>
    /// EN: Ward/Commune.
    /// VI: Phường/Xã.
    /// </summary>
    public string? Ward { get; init; }
    
    /// <summary>
    /// EN: District.
    /// VI: Quận/Huyện.
    /// </summary>
    public string District { get; init; } = string.Empty;
    
    /// <summary>
    /// EN: City.
    /// VI: Thành phố.
    /// </summary>
    public string City { get; init; } = string.Empty;
    
    /// <summary>
    /// EN: Province/State.
    /// VI: Tỉnh/Thành.
    /// </summary>
    public string? Province { get; init; }
    
    /// <summary>
    /// EN: Postal/ZIP code.
    /// VI: Mã bưu điện.
    /// </summary>
    public string? PostalCode { get; init; }
    
    /// <summary>
    /// EN: Country code (ISO 3166-1 alpha-2).
    /// VI: Mã quốc gia (ISO 3166-1 alpha-2).
    /// </summary>
    public string CountryCode { get; init; } = "VN";
    
    /// <summary>
    /// EN: Get full address string.
    /// VI: Lấy chuỗi địa chỉ đầy đủ.
    /// </summary>
    public string FullAddress => $"{Street}, {Ward}, {District}, {City}".Trim(' ', ',');
}

/// <summary>
/// EN: Geographic location value object.
/// VI: Value object vị trí địa lý.
/// </summary>
public record GeoLocation
{
    /// <summary>
    /// EN: Latitude coordinate.
    /// VI: Tọa độ vĩ độ.
    /// </summary>
    public double Latitude { get; init; }
    
    /// <summary>
    /// EN: Longitude coordinate.
    /// VI: Tọa độ kinh độ.
    /// </summary>
    public double Longitude { get; init; }
    
    /// <summary>
    /// EN: Default location (Ho Chi Minh City center).
    /// VI: Vị trí mặc định (trung tâm TP.HCM).
    /// </summary>
    public static GeoLocation Default => new() { Latitude = 10.7769, Longitude = 106.7009 };
    
    /// <summary>
    /// EN: Calculate distance to another location in kilometers.
    /// VI: Tính khoảng cách đến vị trí khác tính bằng km.
    /// </summary>
    public double DistanceTo(GeoLocation other)
    {
        const double R = 6371; // Earth's radius in kilometers
        var lat1 = Latitude * Math.PI / 180;
        var lat2 = other.Latitude * Math.PI / 180;
        var deltaLat = (other.Latitude - Latitude) * Math.PI / 180;
        var deltaLon = (other.Longitude - Longitude) * Math.PI / 180;

        var a = Math.Sin(deltaLat / 2) * Math.Sin(deltaLat / 2) +
                Math.Cos(lat1) * Math.Cos(lat2) *
                Math.Sin(deltaLon / 2) * Math.Sin(deltaLon / 2);
        var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

        return R * c;
    }
}

/// <summary>
/// EN: Operating hours value object.
/// VI: Value object giờ hoạt động.
/// </summary>
public record OperatingHours
{
    /// <summary>
    /// EN: Opening time.
    /// VI: Giờ mở cửa.
    /// </summary>
    public TimeOnly OpenTime { get; init; } = new(8, 0);
    
    /// <summary>
    /// EN: Closing time.
    /// VI: Giờ đóng cửa.
    /// </summary>
    public TimeOnly CloseTime { get; init; } = new(22, 0);
    
    /// <summary>
    /// EN: Days the shop is open.
    /// VI: Các ngày shop mở cửa.
    /// </summary>
    public List<DayOfWeek> OpenDays { get; init; } = new()
    {
        DayOfWeek.Monday,
        DayOfWeek.Tuesday,
        DayOfWeek.Wednesday,
        DayOfWeek.Thursday,
        DayOfWeek.Friday,
        DayOfWeek.Saturday,
        DayOfWeek.Sunday
    };
    
    /// <summary>
    /// EN: Check if currently open.
    /// VI: Kiểm tra có đang mở cửa không.
    /// </summary>
    public bool IsCurrentlyOpen()
    {
        var now = DateTime.UtcNow;
        var currentTime = TimeOnly.FromDateTime(now);
        var currentDay = now.DayOfWeek;
        
        return OpenDays.Contains(currentDay) && 
               currentTime >= OpenTime && 
               currentTime <= CloseTime;
    }
    
    /// <summary>
    /// EN: Default 24/7 operating hours.
    /// VI: Giờ hoạt động mặc định 24/7.
    /// </summary>
    public static OperatingHours TwentyFourSeven => new()
    {
        OpenTime = new TimeOnly(0, 0),
        CloseTime = new TimeOnly(23, 59)
    };
}

/// <summary>
/// EN: Shop feature configuration for multi-vertical support.
/// VI: Cấu hình tính năng shop cho hỗ trợ đa ngành hàng.
/// </summary>
public record ShopFeatures
{
    /// <summary>
    /// EN: Inventory management enabled (Retail, FnB).
    /// VI: Bật quản lý tồn kho (Bán lẻ, FnB).
    /// </summary>
    public bool HasInventory { get; init; }
    
    /// <summary>
    /// EN: Appointment booking enabled (Services, Spa).
    /// VI: Bật đặt lịch hẹn (Dịch vụ, Spa).
    /// </summary>
    public bool HasBooking { get; init; }
    
    /// <summary>
    /// EN: Table management enabled (FnB).
    /// VI: Bật quản lý bàn (FnB).
    /// </summary>
    public bool HasTables { get; init; }
    
    /// <summary>
    /// EN: Kitchen display system enabled (FnB).
    /// VI: Bật hệ thống hiển thị bếp (FnB).
    /// </summary>
    public bool HasKitchen { get; init; }
    
    /// <summary>
    /// EN: Shipping enabled (Retail).
    /// VI: Bật vận chuyển (Bán lẻ).
    /// </summary>
    public bool HasShipping { get; init; }
    
    /// <summary>
    /// EN: Delivery enabled (FnB, Retail).
    /// VI: Bật giao hàng (FnB, Bán lẻ).
    /// </summary>
    public bool HasDelivery { get; init; }
    
    /// <summary>
    /// EN: Default empty features.
    /// VI: Cấu hình tính năng mặc định rỗng.
    /// </summary>
    public static ShopFeatures Empty => new();
    
    /// <summary>
    /// EN: Get default features based on business category.
    /// VI: Lấy cấu hình tính năng mặc định theo ngành nghề.
    /// </summary>
    public static ShopFeatures ForCategory(BusinessCategory category) => category.Id switch
    {
        1 => new ShopFeatures // FoodBeverage
        {
            HasInventory = true,
            HasTables = true,
            HasKitchen = true,
            HasDelivery = true
        },
        2 or 3 or 9 or 10 => new ShopFeatures // Fashion, Electronics, Grocery, HomeFurniture
        {
            HasInventory = true,
            HasShipping = true
        },
        4 or 5 or 6 or 8 => new ShopFeatures // Healthcare, Beauty, Education, Services
        {
            HasBooking = true
        },
        7 => new ShopFeatures // Entertainment
        {
            HasBooking = true,
            HasInventory = true
        },
        _ => new ShopFeatures // Other
        {
            HasInventory = true,
            HasBooking = true
        }
    };
}

