using MediatR;
using TakeoutSaaS.Application.App.Products.Commands;
using TakeoutSaaS.Application.App.Products.Dto;
using TakeoutSaaS.Domain.Products.Entities;
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 BindProductAddonGroupProductsCommandHandler(
    IProductRepository productRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<BindProductAddonGroupProductsCommand, ProductAddonTemplateItemDto>
{
    /// <inheritdoc />
    public async Task<ProductAddonTemplateItemDto> Handle(BindProductAddonGroupProductsCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验加料组是否存在且归属当前门店。
        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. 过滤有效商品并替换关联关系。
        var normalizedProductIds = request.ProductIds
            .Where(item => item > 0)
            .Distinct()
            .ToList();
        var validProductIds = await productRepository.FilterExistingProductIdsAsync(
            tenantId,
            request.StoreId,
            normalizedProductIds,
            cancellationToken);

        await productRepository.RemoveSpecTemplateProductsAsync(existing.Id, tenantId, request.StoreId, cancellationToken);

        var relations = validProductIds
            .Select(productId => new ProductSpecTemplateProduct
            {
                StoreId = request.StoreId,
                TemplateId = existing.Id,
                ProductId = productId
            })
            .ToList();
        if (relations.Count > 0)
        {
            await productRepository.AddSpecTemplateProductsAsync(relations, cancellationToken);
        }

        await productRepository.SaveChangesAsync(cancellationToken);

        // 3. 返回最新快照。
        var options = await productRepository.GetSpecTemplateOptionsByTemplateIdsAsync([existing.Id], tenantId, cancellationToken);
        var latestRelations = 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 = latestRelations
            .GroupBy(x => x.TemplateId)
            .ToDictionary(group => group.Key, group => group.Select(item => item.ProductId).ToList());

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