using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OmsorgCore.Api.Contracts;
using OmsorgCore.Api.Security;
using OmsorgCore.Application.Abstractions;
using OmsorgCore.Domain.Entities;
using OmsorgCore.Domain.Enums;

namespace OmsorgCore.Api.Controllers;

/// <summary>
/// Nachvollziehbarkeit "wer hat wann was am System verändert" - kombiniert automatisch erfasste
/// Entity-Änderungen (AuditSaveChangesInterceptor) und explizit gemeldete Verhaltens-Ereignisse
/// (AuditEvent, z. B. Login/Logout/Session-Kill). Per Default nur für die Rolle Geschäftsführung
/// sichtbar (siehe DbSeeder.SeedBaseRolesAsync).
/// </summary>
[ApiController]
[Authorize]
[Route("api/audit-log")]
public class AuditLogController : ControllerBase
{
    private readonly IAuditLogService _auditLogService;

    public AuditLogController(IAuditLogService auditLogService)
    {
        _auditLogService = auditLogService;
    }

    [HttpGet]
    [RequirePermission(ModuleType.AuditLog, PermissionAction.View)]
    public async Task<ActionResult<PagedResponse<AuditLogEntryResponse>>> GetAll(
        [FromQuery] string? entityType,
        [FromQuery] Guid? entityId,
        [FromQuery] Guid? actorUserId,
        [FromQuery] AuditEventCategory? category,
        [FromQuery] DateTime? fromUtc,
        [FromQuery] DateTime? toUtc,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 50,
        CancellationToken cancellationToken = default)
    {
        page = Math.Max(page, 1);
        pageSize = Math.Clamp(pageSize, 1, 200);

        var (items, totalCount) = await _auditLogService.GetPagedAsync(
            entityType, entityId, actorUserId, category, fromUtc, toUtc, page, pageSize, cancellationToken);

        return Ok(new PagedResponse<AuditLogEntryResponse>(items.Select(ToResponse).ToList(), totalCount, page, pageSize));
    }

    private static AuditLogEntryResponse ToResponse(AuditLogEntry entry) => new(
        entry.Id,
        entry.OccurredAtUtc,
        entry.ActorUserId,
        entry.ActorUsername,
        entry.IpAddress,
        entry.Category.ToString(),
        entry.Action,
        entry.EntityType,
        entry.EntityId,
        entry.Details);
}
