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>
/// 替换 SKU 处理器。
/// </summary>
public sealed class ReplaceProductSkusCommandHandler(
    IProductRepository productRepository,
    ITenantProvider tenantProvider,
    ILogger<ReplaceProductSkusCommandHandler> logger)
    : IRequestHandler<ReplaceProductSkusCommand, IReadOnlyList<ProductSkuDto>>
{
    /// <inheritdoc />
    public async Task<IReadOnlyList<ProductSkuDto>> Handle(ReplaceProductSkusCommand 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. 校验 SKU 唯一性
        var codes = request.Skus.Select(x => x.SkuCode.Trim()).ToList();
        if (codes.Count != codes.Distinct(StringComparer.OrdinalIgnoreCase).Count())
        {
            throw new BusinessException(ErrorCodes.Conflict, "SKU 编码重复");
        }

        // 3. 替换
        await productRepository.RemoveSkusAsync(request.ProductId, tenantId, cancellationToken);
        var entities = request.Skus.Select(x => new ProductSku
        {
            ProductId = request.ProductId,
            SkuCode = x.SkuCode.Trim(),
            Barcode = x.Barcode?.Trim(),
            Price = x.Price,
            OriginalPrice = x.OriginalPrice,
            StockQuantity = x.StockQuantity,
            Weight = x.Weight,
            AttributesJson = x.AttributesJson ?? string.Empty,
            SortOrder = x.SortOrder
        }).ToList();

        await productRepository.AddSkusAsync(entities, cancellationToken);
        await productRepository.SaveChangesAsync(cancellationToken);
        logger.LogInformation("替换商品 {ProductId} 的 SKU 数量 {Count}", request.ProductId, entities.Count);

        return entities.Select(ProductMapping.ToDto).ToList();
    }
}
