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

namespace TakeoutSaaS.Application.Identity.Handlers;

/// <summary>
/// 租户角色模板批量初始化处理器。
/// </summary>
public sealed class InitializeRoleTemplatesCommandHandler(
    IRoleTemplateRepository roleTemplateRepository,
    IMediator mediator)
    : IRequestHandler<InitializeRoleTemplatesCommand, IReadOnlyList<RoleDto>>
{
    /// <inheritdoc />
    public async Task<IReadOnlyList<RoleDto>> Handle(InitializeRoleTemplatesCommand request, CancellationToken cancellationToken)
    {
        // 1. 解析需要初始化的模板编码，默认取全部模板。
        var requestedCodes = request.TemplateCodes?
            .Where(code => !string.IsNullOrWhiteSpace(code))
            .Select(code => code.Trim())
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToArray();

        var availableTemplates = await roleTemplateRepository.GetAllAsync(true, cancellationToken);
        var availableCodes = availableTemplates.Select(t => t.TemplateCode).ToHashSet(StringComparer.OrdinalIgnoreCase);

        var targetCodes = requestedCodes?.Length > 0
            ? requestedCodes
            : availableTemplates.Select(template => template.TemplateCode).ToArray();

        if (targetCodes.Length == 0)
        {
            return Array.Empty<RoleDto>();
        }

        foreach (var code in targetCodes)
        {
            if (!availableCodes.Contains(code))
            {
                throw new BusinessException(ErrorCodes.NotFound, $"角色模板 {code} 不存在或未启用");
            }
        }

        // 2. 逐个复制模板，幂等写入角色与权限。
        var roles = new List<RoleDto>(targetCodes.Length);
        foreach (var templateCode in targetCodes)
        {
            var role = await mediator.Send(new CopyRoleTemplateCommand
            {
                TemplateCode = templateCode
            }, cancellationToken);

            roles.Add(role);
        }

        return roles;
    }
}
