using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OmsorgCore.Api.Contracts;
using OmsorgCore.Api.Security;
using OmsorgCore.Application.Abstractions;
using OmsorgCore.Application.Services;
using OmsorgCore.Domain.Enums;
using OmsorgCore.Engine.Events;

namespace OmsorgCore.Api.Controllers;

/// <summary>
/// Debug-/Admin-Sicht auf aktive Sessions (siehe omsorgapp Debug-Seite). Nur für Rollen mit
/// UserManagement-Rechten (per Default: Administrator, siehe DbSeeder).
/// </summary>
[ApiController]
[Authorize]
[Route("api/admin/sessions")]
public class AdminSessionsController : ControllerBase
{
    private readonly ISessionAdminService _sessionAdminService;
    private readonly ICurrentUserService _currentUserService;
    private readonly IDomainEventDispatcher _dispatcher;

    public AdminSessionsController(
        ISessionAdminService sessionAdminService,
        ICurrentUserService currentUserService,
        IDomainEventDispatcher dispatcher)
    {
        _sessionAdminService = sessionAdminService;
        _currentUserService = currentUserService;
        _dispatcher = dispatcher;
    }

    [HttpGet]
    [RequirePermission(ModuleType.UserManagement, PermissionAction.View)]
    public async Task<ActionResult<IReadOnlyList<SessionResponse>>> GetAll(CancellationToken cancellationToken)
    {
        var sessions = await _sessionAdminService.GetActiveSessionsAsync(cancellationToken);
        return Ok(sessions.Select(s => new SessionResponse(s.Id, s.Username, s.CreatedAt, s.ExpiresAt)));
    }

    [HttpPost("{id:guid}/revoke")]
    [RequirePermission(ModuleType.UserManagement, PermissionAction.Delete)]
    public async Task<IActionResult> Revoke(Guid id, CancellationToken cancellationToken)
    {
        await _sessionAdminService.RevokeSessionAsync(id, cancellationToken);
        await _dispatcher.DispatchAsync(
            new AuditEvent(
                _currentUserService.UserId,
                _currentUserService.Username,
                _currentUserService.IpAddress,
                "SessionRevoked",
                JsonSerializer.Serialize(new { sessionId = id })),
            cancellationToken);
        return NoContent();
    }

    [HttpPost("revoke-all")]
    [RequirePermission(ModuleType.UserManagement, PermissionAction.Delete)]
    public async Task<IActionResult> RevokeAll(CancellationToken cancellationToken)
    {
        await _sessionAdminService.RevokeAllSessionsAsync(cancellationToken);
        await _dispatcher.DispatchAsync(
            new AuditEvent(
                _currentUserService.UserId,
                _currentUserService.Username,
                _currentUserService.IpAddress,
                "AllSessionsRevoked"),
            cancellationToken);
        return NoContent();
    }
}
