using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Stores.Commands;
using TakeoutSaaS.Application.App.Stores.Dto;
using TakeoutSaaS.Domain.Merchants.Repositories;
using TakeoutSaaS.Domain.Stores.Entities;
using TakeoutSaaS.Domain.Stores.Enums;
using TakeoutSaaS.Domain.Stores.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;

namespace TakeoutSaaS.Application.App.Stores.Handlers;

/// <summary>
/// 创建门店命令处理器。
/// </summary>
public sealed class CreateStoreCommandHandler(
    IStoreRepository storeRepository,
    IMerchantRepository merchantRepository,
    ILogger<CreateStoreCommandHandler> logger)
    : IRequestHandler<CreateStoreCommand, StoreDto>
{
    /// <inheritdoc />
    public async Task<StoreDto> Handle(CreateStoreCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验商户存在并解析租户
        var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, cancellationToken);
        if (merchant == null)
        {
            throw new BusinessException(ErrorCodes.NotFound, "商户不存在");
        }
        var tenantId = merchant.TenantId;

        // 2. (空行后) 校验门店坐标唯一性（100 米内禁止重复）
        if (request.Longitude.HasValue && request.Latitude.HasValue)
        {
            var isDuplicate = await storeRepository.ExistsStoreWithinDistanceAsync(
                request.MerchantId,
                tenantId,
                request.Longitude.Value,
                request.Latitude.Value,
                100,
                cancellationToken);
            if (isDuplicate)
            {
                throw new BusinessException(ErrorCodes.Conflict, "该位置已存在门店");
            }
        }

        // 3. (空行后) 计算审核与经营状态
        var now = DateTime.UtcNow;
        var isSameEntity = request.OwnershipType == StoreOwnershipType.SameEntity;
        var auditStatus = isSameEntity ? StoreAuditStatus.Activated : StoreAuditStatus.Draft;
        var businessStatus = StoreBusinessStatus.Resting;
        DateTime? activatedAt = isSameEntity ? now : null;

        // 4. (空行后) 构建实体
        var store = new Store
        {
            TenantId = tenantId,
            MerchantId = request.MerchantId,
            Code = request.Code.Trim(),
            Name = request.Name.Trim(),
            Phone = request.Phone?.Trim(),
            ManagerName = request.ManagerName?.Trim(),
            Status = request.Status,
            SignboardImageUrl = request.SignboardImageUrl?.Trim(),
            OwnershipType = request.OwnershipType,
            AuditStatus = auditStatus,
            BusinessStatus = businessStatus,
            CategoryId = request.CategoryId,
            ActivatedAt = activatedAt,
            Province = request.Province?.Trim(),
            City = request.City?.Trim(),
            District = request.District?.Trim(),
            Address = request.Address?.Trim(),
            Longitude = request.Longitude,
            Latitude = request.Latitude,
            Announcement = request.Announcement?.Trim(),
            Tags = request.Tags?.Trim(),
            DeliveryRadiusKm = request.DeliveryRadiusKm,
            SupportsDineIn = request.SupportsDineIn,
            SupportsPickup = request.SupportsPickup,
            SupportsDelivery = request.SupportsDelivery,
            SupportsReservation = request.SupportsReservation,
            SupportsQueueing = request.SupportsQueueing
        };

        // 5. (空行后) 持久化门店以获取标识
        await storeRepository.AddStoreAsync(store, cancellationToken);
        await storeRepository.SaveChangesAsync(cancellationToken);

        // 6. (空行后) 初始化费用配置
        await storeRepository.AddStoreFeeAsync(new StoreFee
        {
            TenantId = tenantId,
            StoreId = store.Id,
            MinimumOrderAmount = 0m,
            BaseDeliveryFee = 0m,
            PackagingFeeMode = PackagingFeeMode.Fixed,
            OrderPackagingFeeMode = OrderPackagingFeeMode.Fixed,
            FixedPackagingFee = 0m
        }, cancellationToken);
        await storeRepository.SaveChangesAsync(cancellationToken);
        logger.LogInformation("创建门店 {StoreId} - {StoreName}", store.Id, store.Name);

        // 7. (空行后) 返回 DTO
        return StoreMapping.ToDto(store);
    }
}
