using MediatR;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Dto;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;

namespace TakeoutSaaS.Application.App.Tenants.Handlers;

/// <summary>
/// 创建公告处理器。
/// </summary>
public sealed class CreateTenantAnnouncementCommandHandler(
    ITenantAnnouncementRepository announcementRepository,
    ICurrentUserAccessor currentUserAccessor)
    : IRequestHandler<CreateTenantAnnouncementCommand, TenantAnnouncementDto>
{
    /// <summary>
    /// 处理创建租户公告请求。
    /// </summary>
    /// <param name="request">创建命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>公告 DTO。</returns>
    public async Task<TenantAnnouncementDto> Handle(CreateTenantAnnouncementCommand request, CancellationToken cancellationToken)
    {
        // 1. 校验标题与内容
        if (string.IsNullOrWhiteSpace(request.Title) || string.IsNullOrWhiteSpace(request.Content))
        {
            throw new BusinessException(ErrorCodes.ValidationFailed, "公告标题和内容不能为空");
        }

        if (string.IsNullOrWhiteSpace(request.TargetType))
        {
            throw new BusinessException(ErrorCodes.ValidationFailed, "目标受众类型不能为空");
        }

        if (request.TenantId == 0 && request.PublisherScope != PublisherScope.Platform)
        {
            throw new BusinessException(ErrorCodes.ValidationFailed, "TenantId=0 仅允许平台公告");
        }

        // 2. 构建公告实体
        var tenantId = request.PublisherScope == PublisherScope.Platform ? 0 : request.TenantId;
        var publisherUserId = currentUserAccessor.UserId == 0 ? (long?)null : currentUserAccessor.UserId;
        var announcement = new TenantAnnouncement
        {
            TenantId = tenantId,
            Title = request.Title.Trim(),
            Content = request.Content,
            AnnouncementType = request.AnnouncementType,
            Priority = request.Priority,
            EffectiveFrom = request.EffectiveFrom,
            EffectiveTo = request.EffectiveTo,
            PublisherScope = request.PublisherScope,
            PublisherUserId = publisherUserId,
            Status = AnnouncementStatus.Draft,
            TargetType = request.TargetType.Trim(),
            TargetParameters = request.TargetParameters
        };

        // 3. 持久化并返回 DTO
        await announcementRepository.AddAsync(announcement, cancellationToken);
        await announcementRepository.SaveChangesAsync(cancellationToken);

        return announcement.ToDto(false, null);
    }
}
