using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using IamService.API.Application.Common;
using IamService.API.Application.Commands.PrivilegedAccess;
using IamService.API.Application.Queries.PrivilegedAccess;

namespace IamService.API.Controllers;

[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/privileged-access")]
[Authorize(AuthenticationSchemes = "Bearer")]
[Authorize(Policy = "RequireSuperAdmin")]
[SwaggerTag("Privileged Access Management (PAM) - requires SuperAdmin role")]
public class PrivilegedAccessController : ControllerBase
{
    private readonly IMediator _mediator;
    public PrivilegedAccessController(IMediator mediator) => _mediator = mediator;

    [HttpPost("request")]
    [SwaggerOperation(Summary = "Request privileged access", OperationId = "RequestPrivilegedAccess")]
    public async Task<IActionResult> RequestAccess([FromBody] RequestPamRequest request, CancellationToken ct = default)
    {
        try
        {
            var id = await _mediator.Send(new RequestPrivilegedAccessCommand(
                request.UserId, request.RoleId, request.ResourceScope, 
                request.Reason, request.GrantedByUserId, request.DurationMinutes), ct);
            return Ok(ApiResponse<object>.Ok(new { GrantId = id, ExpiresInMinutes = request.DurationMinutes }));
        }
        catch (Exception ex) { return BadRequest(ApiResponse<object>.Fail("ERROR", ex.Message)); }
    }

    [HttpGet("active")]
    [SwaggerOperation(Summary = "Get active privileged grants", OperationId = "GetActivePrivilegedAccess")]
    public async Task<IActionResult> GetActive([FromQuery] Guid userId, CancellationToken ct = default)
    {
        var grants = await _mediator.Send(new GetActivePrivilegedAccessQuery(userId), ct);
        return Ok(ApiResponse<IEnumerable<PrivilegedAccessDto>>.Ok(grants));
    }

    [HttpPost("{id:guid}/revoke")]
    [SwaggerOperation(Summary = "Revoke privileged access", OperationId = "RevokePrivilegedAccess")]
    public async Task<IActionResult> Revoke([FromRoute] Guid id, [FromBody] RevokePamRequest request, CancellationToken ct = default)
    {
        try
        {
            await _mediator.Send(new RevokePrivilegedAccessCommand(id, request.RevokedByUserId, request.Reason), ct);
            return Ok(ApiResponse<object>.Ok(new { Message = "Privileged access revoked" }));
        }
        catch (Exception ex) { return BadRequest(ApiResponse<object>.Fail("ERROR", ex.Message)); }
    }
}

#region Request Models
public record RequestPamRequest(Guid UserId, Guid RoleId, string ResourceScope, string? Reason, Guid GrantedByUserId, int DurationMinutes = 60);
public record RevokePamRequest(Guid RevokedByUserId, string? Reason);
#endregion
