using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Meezi.API.Models.Audit;
using Meezi.Core.Authorization;
using Meezi.Core.Interfaces;
using Meezi.Infrastructure.Data;
using Meezi.Shared;

namespace Meezi.API.Controllers;

/// <summary>
/// Read-only access to the immutable POS / management audit trail. Gated by
/// <see cref="Permission.ViewReports"/>; branch-scoped sessions only ever see
/// their own branch's entries (enforced by the DB-level branch isolation filter),
/// café-wide owners see everything.
/// </summary>
[Route("api/cafes/{cafeId}/audit-logs")]
public class AuditController : CafeApiControllerBase
{
    private const int MaxPageSize = 100;

    private readonly AppDbContext _db;

    public AuditController(AppDbContext db)
    {
        _db = db;
    }

    [HttpGet]
    public async Task<IActionResult> List(
        string cafeId,
        ITenantContext tenant,
        CancellationToken ct,
        [FromQuery] string? category = null,
        [FromQuery] string? action = null,
        [FromQuery] string? branchId = null,
        [FromQuery] string? entityType = null,
        [FromQuery] string? entityId = null,
        [FromQuery] DateTime? from = null,
        [FromQuery] DateTime? to = null,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 50)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        if (EnsurePermission(tenant, Permission.ViewReports) is { } forbidden) return forbidden;

        if (page < 1) page = 1;
        if (pageSize < 1) pageSize = 50;
        if (pageSize > MaxPageSize) pageSize = MaxPageSize;

        var query = _db.AuditLogs.AsNoTracking().Where(x => x.CafeId == cafeId);

        if (!string.IsNullOrWhiteSpace(category))
            query = query.Where(x => x.Category == category);
        if (!string.IsNullOrWhiteSpace(action))
            query = query.Where(x => x.Action == action);
        if (!string.IsNullOrWhiteSpace(branchId))
            query = query.Where(x => x.BranchId == branchId);
        if (!string.IsNullOrWhiteSpace(entityType))
            query = query.Where(x => x.EntityType == entityType);
        if (!string.IsNullOrWhiteSpace(entityId))
            query = query.Where(x => x.EntityId == entityId);
        if (from is { } f)
            query = query.Where(x => x.CreatedAt >= f);
        if (to is { } t)
            query = query.Where(x => x.CreatedAt <= t);

        var total = await query.CountAsync(ct);

        var items = await query
            .OrderByDescending(x => x.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(x => new AuditLogDto(
                x.Id,
                x.Category,
                x.Action,
                x.EntityType,
                x.EntityId,
                x.BranchId,
                x.ActorId,
                x.ActorName,
                x.ActorRole,
                x.Summary,
                x.DetailsJson,
                x.CreatedAt))
            .ToListAsync(ct);

        return Ok(new PagedApiResponse<AuditLogDto>(true, items, new PagedMeta(total, page, pageSize)));
    }
}
