using MediatR;
using TakeoutSaaS.Application.App.Products.Commands;
using TakeoutSaaS.Application.App.Products.Dto;
using TakeoutSaaS.Domain.Products.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.App.Products.Handlers;

/// <summary>
/// 修改加料组状态命令处理器。
/// </summary>
public sealed class ChangeProductAddonGroupStatusCommandHandler(
    IProductRepository productRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<ChangeProductAddonGroupStatusCommand, ProductAddonTemplateItemDto>
{
    /// <inheritdoc />
    public async Task<ProductAddonTemplateItemDto> Handle(ChangeProductAddonGroupStatusCommand request, CancellationToken cancellationToken)
    {
        // 1. 解析状态并验证加料组归属。
        if (!ProductAddonTemplateMapping.TryParseStatus(request.Status, out var isEnabled))
        {
            throw new BusinessException(ErrorCodes.BadRequest, "status 参数不合法");
        }

        var tenantId = tenantProvider.GetCurrentTenantId();
        var existing = await productRepository.FindAddonTemplateByIdAsync(request.GroupId, tenantId, cancellationToken);
        if (existing is null || existing.StoreId != request.StoreId)
        {
            throw new BusinessException(ErrorCodes.NotFound, "加料组不存在");
        }

        // 2. 保存状态变更。
        existing.IsEnabled = isEnabled;
        await productRepository.UpdateSpecTemplateAsync(existing, cancellationToken);
        await productRepository.SaveChangesAsync(cancellationToken);

        // 3. 返回完整快照。
        var options = await productRepository.GetSpecTemplateOptionsByTemplateIdsAsync([existing.Id], tenantId, cancellationToken);
        var relations = await productRepository.GetSpecTemplateProductsByTemplateIdsAsync([existing.Id], tenantId, request.StoreId, cancellationToken);
        var optionsLookup = options
            .GroupBy(x => x.TemplateId)
            .ToDictionary(group => group.Key, group => group.OrderBy(item => item.SortOrder).ThenBy(item => item.Id).ToList());
        var productIdsLookup = relations
            .GroupBy(x => x.TemplateId)
            .ToDictionary(group => group.Key, group => group.Select(item => item.ProductId).ToList());

        return ProductAddonTemplateDtoFactory.ToDto(existing, optionsLookup, productIdsLookup);
    }
}
