using MediatR;
using TakeoutSaaS.Application.Identity.Commands;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 创建角色处理器。
/// </summary>
public sealed class CreateRoleCommandHandler(
    IRoleRepository roleRepository,
    ITenantProvider tenantProvider)
    : IRequestHandler<CreateRoleCommand, RoleDto>
{
    /// <summary>
    /// 处理创建角色请求。
    /// </summary>
    /// <param name="request">创建命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>创建后的角色 DTO。</returns>
    public async Task<RoleDto> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
    {
        // 1. 获取租户上下文
        var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();

        // 2. 归一化输入并校验唯一
        var name = request.Name?.Trim() ?? string.Empty;
        var code = request.Code?.Trim() ?? string.Empty;
        if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(code))
        {
            throw new BusinessException(ErrorCodes.BadRequest, "角色名称与编码不能为空");
        }

        var exists = await roleRepository.FindByCodeAsync(code, tenantId, cancellationToken);
        if (exists is not null)
        {
            throw new BusinessException(ErrorCodes.Conflict, "角色编码已存在");
        }

        // 3. 构建角色实体
        var role = new Role
        {
            TenantId = tenantId,
            Name = name,
            Code = code,
            Description = request.Description
        };

        // 4. 持久化
        await roleRepository.AddAsync(role, cancellationToken);
        await roleRepository.SaveChangesAsync(cancellationToken);

        // 5. 返回 DTO
        return new RoleDto
        {
            Id = role.Id,
            TenantId = role.TenantId,
            Name = role.Name,
            Code = role.Code,
            Description = role.Description
        };
    }
}
