// EN: Handlers for subscription queries.
// VI: Handlers cho các subscription queries.

using MediatR;
using MerchantService.Domain.AggregatesModel.MerchantAggregate;
using MerchantService.Domain.AggregatesModel.MerchantStaffAggregate;
using MerchantService.Domain.AggregatesModel.ShopAggregate;

namespace MerchantService.API.Application.Queries.Subscriptions;

/// <summary>
/// EN: Static subscription plan definitions.
/// VI: Định nghĩa tĩnh các gói đăng ký.
/// </summary>
internal static class SubscriptionPlans
{
    public static readonly IReadOnlyList<SubscriptionPlanDto> All = new List<SubscriptionPlanDto>
    {
        new()
        {
            Id = 0, Name = "Starter", Description = "Free plan for small businesses / Gói miễn phí cho doanh nghiệp nhỏ",
            MonthlyPrice = 0m, MaxShops = 1, MaxStaffPerShop = 3, MaxProducts = 50,
            HasAnalytics = false, HasPrioritySupport = false
        },
        new()
        {
            Id = 1, Name = "Growth", Description = "For growing businesses / Cho doanh nghiệp đang phát triển",
            MonthlyPrice = 299_000m, MaxShops = 3, MaxStaffPerShop = 10, MaxProducts = 500,
            HasAnalytics = true, HasPrioritySupport = false
        },
        new()
        {
            Id = 2, Name = "Pro", Description = "For professional businesses / Cho doanh nghiệp chuyên nghiệp",
            MonthlyPrice = 799_000m, MaxShops = 10, MaxStaffPerShop = 50, MaxProducts = 5000,
            HasAnalytics = true, HasPrioritySupport = true
        },
        new()
        {
            Id = 3, Name = "Enterprise", Description = "For large enterprises / Cho doanh nghiệp lớn",
            MonthlyPrice = 1_999_000m, MaxShops = 999, MaxStaffPerShop = 999, MaxProducts = 99999,
            HasAnalytics = true, HasPrioritySupport = true
        }
    };

    public static SubscriptionPlanDto GetById(int planId) =>
        All.FirstOrDefault(p => p.Id == planId) ?? All[0];
}

/// <summary>
/// EN: Handler for GetSubscriptionQuery — returns current merchant's subscription info.
/// VI: Handler cho GetSubscriptionQuery — trả về thông tin gói đăng ký của merchant hiện tại.
/// </summary>
public class GetSubscriptionQueryHandler : IRequestHandler<GetSubscriptionQuery, SubscriptionDto?>
{
    private readonly IMerchantRepository _merchantRepository;

    public GetSubscriptionQueryHandler(
        IMerchantRepository merchantRepository)
    {
        _merchantRepository = merchantRepository;
    }

    public async Task<SubscriptionDto?> Handle(GetSubscriptionQuery request, CancellationToken cancellationToken)
    {
        // EN: Use user ID passed from the controller
        // VI: Dùng user ID được truyền từ controller
        var merchant = await _merchantRepository.GetByUserIdAsync(request.UserId, cancellationToken);
        if (merchant == null) return null;

        var plan = SubscriptionPlans.GetById(merchant.SubscriptionPlanId);

        return new SubscriptionDto
        {
            PlanId = plan.Id,
            PlanName = plan.Name,
            MaxShops = plan.MaxShops,
            MaxStaffPerShop = plan.MaxStaffPerShop,
            MaxProducts = plan.MaxProducts,
            HasAnalytics = plan.HasAnalytics,
            HasPrioritySupport = plan.HasPrioritySupport
        };
    }
}

/// <summary>
/// EN: Handler for GetSubscriptionPlansQuery — returns all available plans.
/// VI: Handler cho GetSubscriptionPlansQuery — trả về tất cả các gói có sẵn.
/// </summary>
public class GetSubscriptionPlansQueryHandler : IRequestHandler<GetSubscriptionPlansQuery, IReadOnlyList<SubscriptionPlanDto>>
{
    public Task<IReadOnlyList<SubscriptionPlanDto>> Handle(GetSubscriptionPlansQuery request, CancellationToken cancellationToken)
    {
        return Task.FromResult(SubscriptionPlans.All);
    }
}

/// <summary>
/// EN: Handler for GetSubscriptionUsageQuery — returns current usage vs plan limits.
/// VI: Handler cho GetSubscriptionUsageQuery — trả về mức sử dụng hiện tại so với giới hạn gói.
/// </summary>
public class GetSubscriptionUsageQueryHandler : IRequestHandler<GetSubscriptionUsageQuery, SubscriptionUsageDto?>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly IMerchantStaffRepository _staffRepository;

    public GetSubscriptionUsageQueryHandler(
        IMerchantRepository merchantRepository,
        IShopRepository shopRepository,
        IMerchantStaffRepository staffRepository)
    {
        _merchantRepository = merchantRepository;
        _shopRepository = shopRepository;
        _staffRepository = staffRepository;
    }

    public async Task<SubscriptionUsageDto?> Handle(GetSubscriptionUsageQuery request, CancellationToken cancellationToken)
    {
        // EN: Use user ID passed from the controller
        // VI: Dùng user ID được truyền từ controller
        var merchant = await _merchantRepository.GetByUserIdAsync(request.UserId, cancellationToken);
        if (merchant == null) return null;

        var plan = SubscriptionPlans.GetById(merchant.SubscriptionPlanId);
        var shops = await _shopRepository.GetByMerchantIdAsync(merchant.Id, cancellationToken);
        var staff = await _staffRepository.GetByMerchantIdAsync(merchant.Id, cancellationToken);

        return new SubscriptionUsageDto
        {
            PlanId = plan.Id,
            PlanName = plan.Name,
            ShopsUsed = shops.Count,
            ShopsLimit = plan.MaxShops,
            StaffUsed = staff.Count,
            StaffLimit = plan.MaxStaffPerShop * shops.Count,
            // EN: Product count not tracked here — would need catalog service integration.
            // VI: Số sản phẩm không theo dõi ở đây — cần tích hợp catalog service.
            ProductsUsed = 0,
            ProductsLimit = plan.MaxProducts
        };
    }
}
