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.Abstractions.Tenancy;
using TakeoutSaaS.Shared.Web.Api;

namespace TakeoutSaaS.AdminApi.Controllers;

/// <summary>
/// 租户角色管理（实例层）。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/admin/v{version:apiVersion}/tenants/{tenantId:long}/roles")]
public sealed class TenantRolesController(IMediator mediator, ITenantProvider tenantProvider) : BaseApiController
{
    private const long PlatformRootTenantId = 1000000000001;

    /// <summary>
    /// 租户角色分页。
    /// </summary>
    [HttpGet]
    [PermissionAuthorize("identity:role:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<RoleDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<RoleDto>>> List(
        long tenantId,
        [FromQuery] SearchRolesQuery query,
        CancellationToken cancellationToken)
    {
        // 1. 校验路由租户与上下文一致（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<PagedResult<RoleDto>>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 绑定租户并查询角色分页
        var request = new SearchRolesQuery
        {
            TenantId = tenantId,
            Keyword = query.Keyword,
            Page = query.Page,
            PageSize = query.PageSize,
            SortBy = query.SortBy,
            SortDescending = query.SortDescending
        };
        var result = await mediator.Send(request, cancellationToken);

        // 3. 返回分页数据
        return ApiResponse<PagedResult<RoleDto>>.Ok(result);
    }

    /// <summary>
    /// 角色详情（含权限）。
    /// </summary>
    [HttpGet("{roleId:long}")]
    [PermissionAuthorize("identity:role:read")]
    [ProducesResponseType(typeof(ApiResponse<RoleDetailDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<RoleDetailDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<RoleDetailDto>> Detail(long tenantId, long roleId, CancellationToken cancellationToken)
    {
        // 1. 校验租户上下文（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<RoleDetailDto>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 查询角色详情
        var result = await mediator.Send(new RoleDetailQuery { RoleId = roleId, TenantId = tenantId }, cancellationToken);

        // 3. 返回数据或 404
        return result is null
            ? ApiResponse<RoleDetailDto>.Error(StatusCodes.Status404NotFound, "角色不存在")
            : ApiResponse<RoleDetailDto>.Ok(result);
    }

    /// <summary>
    /// 创建角色。
    /// </summary>
    [HttpPost]
    [PermissionAuthorize("identity:role:create")]
    [ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<RoleDto>> Create(
        long tenantId,
        [FromBody, Required] CreateRoleCommand command,
        CancellationToken cancellationToken)
    {
        // 1. 校验租户上下文（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<RoleDto>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 创建角色
        var result = await mediator.Send(command with { TenantId = tenantId }, cancellationToken);

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

    /// <summary>
    /// 更新角色。
    /// </summary>
    [HttpPut("{roleId:long}")]
    [PermissionAuthorize("identity:role:update")]
    [ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<RoleDto>> Update(
        long tenantId,
        long roleId,
        [FromBody, Required] UpdateRoleCommand command,
        CancellationToken cancellationToken)
    {
        // 1. 校验租户上下文（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<RoleDto>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 绑定角色 ID
        command = command with { RoleId = roleId, TenantId = tenantId };

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

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

    /// <summary>
    /// 删除角色。
    /// </summary>
    [HttpDelete("{roleId:long}")]
    [PermissionAuthorize("identity:role:delete")]
    [ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<bool>> Delete(long tenantId, long roleId, CancellationToken cancellationToken)
    {
        // 1. 校验租户上下文（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<bool>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 执行删除
        var command = new DeleteRoleCommand { RoleId = roleId, TenantId = tenantId };
        var result = await mediator.Send(command, cancellationToken);

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

    /// <summary>
    /// 获取角色权限列表。
    /// </summary>
    [HttpGet("{roleId:long}/permissions")]
    [PermissionAuthorize("identity:role:read")]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<PermissionDto>>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<IReadOnlyList<PermissionDto>>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<IReadOnlyList<PermissionDto>>> GetPermissions(
        long tenantId,
        long roleId,
        CancellationToken cancellationToken)
    {
        // 1. 校验租户上下文（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<IReadOnlyList<PermissionDto>>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 查询角色详情并提取权限
        var detail = await mediator.Send(new RoleDetailQuery { RoleId = roleId, TenantId = tenantId }, cancellationToken);
        if (detail is null)
        {
            return ApiResponse<IReadOnlyList<PermissionDto>>.Error(StatusCodes.Status404NotFound, "角色不存在");
        }

        // 3. 返回权限集合
        return ApiResponse<IReadOnlyList<PermissionDto>>.Ok(detail.Permissions);
    }

    /// <summary>
    /// 覆盖角色权限。
    /// </summary>
    [HttpPut("{roleId:long}/permissions")]
    [PermissionAuthorize("identity:role:bind-permission")]
    [ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<bool>> BindPermissions(
        long tenantId,
        long roleId,
        [FromBody, Required] BindRolePermissionsCommand command,
        CancellationToken cancellationToken)
    {
        // 1. 校验租户上下文（超管租户 1000000000001 放行）
        var currentTenantId = tenantProvider.GetCurrentTenantId();
        if (currentTenantId != PlatformRootTenantId && tenantId != currentTenantId)
        {
            return ApiResponse<bool>.Error(StatusCodes.Status400BadRequest, "租户上下文不一致");
        }

        // 2. 绑定角色 ID
        command = command with { RoleId = roleId, TenantId = tenantId };

        // 3. 覆盖授权
        var result = await mediator.Send(command, cancellationToken);
        return ApiResponse<bool>.Ok(result);
    }
}
