using MediatR;
using Microsoft.Extensions.Logging;
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 ReplaceProductAttributesCommandHandler(
    IProductRepository productRepository,
    ITenantProvider tenantProvider,
    ILogger<ReplaceProductAttributesCommandHandler> logger)
    : IRequestHandler<ReplaceProductAttributesCommand, IReadOnlyList<ProductAttributeGroupDto>>
{
    /// <inheritdoc />
    public async Task<IReadOnlyList<ProductAttributeGroupDto>> Handle(ReplaceProductAttributesCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验商品
        var tenantId = tenantProvider.GetCurrentTenantId();
        var product = await productRepository.FindByIdAsync(request.ProductId, tenantId, cancellationToken);
        if (product is null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "商品不存在");
        }

        // 2. 组名唯一
        var groupNames = request.AttributeGroups.Select(x => x.Name.Trim()).ToList();
        if (groupNames.Count != groupNames.Distinct(StringComparer.OrdinalIgnoreCase).Count())
        {
            throw new BusinessException(ErrorCodes.Conflict, "规格组名称重复");
        }

        // 3. 替换
        await productRepository.RemoveAttributeGroupsAsync(request.ProductId, tenantId, cancellationToken);

        var groupEntities = request.AttributeGroups.Select(g => new ProductAttributeGroup
        {
            ProductId = request.ProductId,
            Name = g.Name.Trim(),
            SelectionType = (Domain.Products.Enums.AttributeSelectionType)g.SelectionType,
            SortOrder = g.SortOrder
        }).ToList();

        // 4. 持久化（分批保障 FK 正确）
        await productRepository.AddAttributeGroupsAsync(groupEntities, [], cancellationToken);
        await productRepository.SaveChangesAsync(cancellationToken);

        // 重新建立选项的 GroupId 映射
        var groupIdLookup = groupEntities.Zip(request.AttributeGroups, (entity, dto) => (entity, dto))
            .ToDictionary(x => x.dto, x => x.entity.Id);

        var optionEntities = request.AttributeGroups
            .SelectMany(dto => dto.Options.Select(o => new ProductAttributeOption
            {
                AttributeGroupId = groupIdLookup[dto],
                Name = o.Name.Trim(),
                SortOrder = o.SortOrder
            }))
            .ToList();

        await productRepository.AddAttributeGroupsAsync([], optionEntities, cancellationToken);
        await productRepository.SaveChangesAsync(cancellationToken);
        logger.LogInformation("替换商品 {ProductId} 规格组 {GroupCount} 个", request.ProductId, groupEntities.Count);

        // 5. 返回 DTO
        return groupEntities
            .Select(g => ProductMapping.ToDto(g, optionEntities.Where(o => o.AttributeGroupId == g.Id).ToList()))
            .ToList();
    }
}
