using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using TakeoutSaaS.Application.Identity.Commands;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
using TakeoutSaaS.Module.Authorization.Attributes;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;

namespace TakeoutSaaS.AdminApi.Controllers;

/// <summary>
/// 角色模板管理（平台蓝本）。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/admin/v{version:apiVersion}/role-templates")]
public sealed class RoleTemplatesController(IMediator mediator) : BaseApiController
{
    /// <summary>
    /// 分页查询角色模板。
    /// </summary>
    /// <param name="isActive">是否启用筛选。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>角色模板列表。</returns>
    [HttpGet]
    [PermissionAuthorize("identity:role:read")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<RoleTemplateDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<RoleTemplateDto>>> List([FromQuery] bool? isActive, CancellationToken cancellationToken)
    {
        // 1. 构造查询参数
        var query = new ListRoleTemplatesQuery { IsActive = isActive };

        // 2. 查询模板集合
        var result = await mediator.Send(query, cancellationToken);

        // 3. 返回模板列表
        return ApiResponse<IReadOnlyList<RoleTemplateDto>>.Ok(result);
    }

    /// <summary>
    /// 克隆角色模板。
    /// </summary>
    /// <param name="templateCode">源模板编码。</param>
    /// <param name="command">克隆命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>新模板详情。</returns>
    [HttpPost("{templateCode}/clone")]
    [PermissionAuthorize("role-template:create")]
    [ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<RoleTemplateDto>> Clone(
        string templateCode,
        [FromBody, Required] CloneRoleTemplateCommand command,
        CancellationToken cancellationToken)
    {
        // 1. 绑定源模板编码
        command = command with { SourceTemplateCode = templateCode };

        // 2. 执行克隆
        var result = await mediator.Send(command, cancellationToken);

        // 3. 返回新模板
        return ApiResponse<RoleTemplateDto>.Ok(result);
    }

    /// <summary>
    /// 获取角色模板详情。
    /// </summary>
    /// <param name="templateCode">模板编码。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>角色模板详情。</returns>
    [HttpGet("{templateCode}")]
    [PermissionAuthorize("identity:role:read")]
    [ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<RoleTemplateDto>> Detail(string templateCode, CancellationToken cancellationToken)
    {
        // 1. 查询模板详情
        var result = await mediator.Send(new GetRoleTemplateQuery { TemplateCode = templateCode }, cancellationToken);

        // 2. 返回模板或 404
        return result is null
            ? ApiResponse<RoleTemplateDto>.Error(StatusCodes.Status404NotFound, "角色模板不存在")
            : ApiResponse<RoleTemplateDto>.Ok(result);
    }

    /// <summary>
    /// 创建角色模板。
    /// </summary>
    /// <param name="command">创建命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>创建后的模板。</returns>
    [HttpPost]
    [PermissionAuthorize("role-template:create")]
    [ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<RoleTemplateDto>> Create([FromBody, Required] CreateRoleTemplateCommand command, CancellationToken cancellationToken)
    {
        // 1. 创建模板
        var result = await mediator.Send(command, cancellationToken);

        // 2. 返回创建结果
        return ApiResponse<RoleTemplateDto>.Ok(result);
    }

    /// <summary>
    /// 获取模板的权限列表。
    /// </summary>
    /// <param name="templateCode">模板编码。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>权限集合。</returns>
    [HttpGet("{templateCode}/permissions")]
    [PermissionAuthorize("identity:role:read")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<PermissionTemplateDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<PermissionTemplateDto>>> GetPermissions(string templateCode, CancellationToken cancellationToken)
    {
        // 1. 查询模板权限
        var result = await mediator.Send(new RoleTemplatePermissionsQuery { TemplateCode = templateCode }, cancellationToken);

        // 2. 返回权限集合
        return ApiResponse<IReadOnlyList<PermissionTemplateDto>>.Ok(result);
    }

    /// <summary>
    /// 更新角色模板。
    /// </summary>
    /// <param name="templateCode">模板编码。</param>
    /// <param name="command">更新命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>更新后的模板。</returns>
    [HttpPut("{templateCode}")]
    [PermissionAuthorize("role-template:update")]
    [ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<RoleTemplateDto>> Update(
        string templateCode,
        [FromBody, Required] UpdateRoleTemplateCommand command,
        CancellationToken cancellationToken)
    {
        // 1. 绑定模板编码
        command = command with { TemplateCode = templateCode };

        // 2. 执行更新
        var result = await mediator.Send(command, cancellationToken);

        // 3. 返回更新结果或 404
        return result is null
            ? ApiResponse<RoleTemplateDto>.Error(StatusCodes.Status404NotFound, "角色模板不存在")
            : ApiResponse<RoleTemplateDto>.Ok(result);
    }

    /// <summary>
    /// 删除角色模板。
    /// </summary>
    /// <param name="templateCode">模板编码。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>删除结果。</returns>
    [HttpDelete("{templateCode}")]
    [PermissionAuthorize("role-template:delete")]
    [ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<bool>> Delete(string templateCode, CancellationToken cancellationToken)
    {
        // 1. 执行删除
        var result = await mediator.Send(new DeleteRoleTemplateCommand { TemplateCode = templateCode }, cancellationToken);

        // 2. 返回执行结果
        return ApiResponse<bool>.Ok(result);
    }

    /// <summary>
    /// 为当前租户批量初始化预置角色模板。
    /// </summary>
    /// <param name="command">初始化命令。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>生成的租户角色列表。</returns>
    [HttpPost("init")]
    [PermissionAuthorize("identity:role:create")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<RoleDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<RoleDto>>> Initialize(
        [FromBody] InitializeRoleTemplatesCommand? command,
        CancellationToken cancellationToken)
    {
        // 1. 确保命令存在
        command ??= new InitializeRoleTemplatesCommand();

        // 2. 初始化模板到租户
        var result = await mediator.Send(command, cancellationToken);

        // 3. 返回新建的角色列表
        return ApiResponse<IReadOnlyList<RoleDto>>.Ok(result);
    }

    /// <summary>
    /// 将单个模板初始化到当前租户。
    /// </summary>
    /// <param name="templateCode">模板编码。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>生成的角色列表。</returns>
    [HttpPost("{templateCode}/initialize-tenant")]
    [PermissionAuthorize("identity:role:create")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<RoleDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<IReadOnlyList<RoleDto>>> InitializeSingle(string templateCode, CancellationToken cancellationToken)
    {
        // 1. 构造初始化命令
        var command = new InitializeRoleTemplatesCommand
        {
            TemplateCodes = new[] { templateCode }
        };

        // 2. 初始化模板到租户
        var result = await mediator.Send(command, cancellationToken);

        // 3. 返回生成的角色列表
        return ApiResponse<IReadOnlyList<RoleDto>>.Ok(result);
    }
}
