using foodmarket.Application.Common;
using foodmarket.Infrastructure.Persistence;
using foodmarket.Api.Infrastructure.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace foodmarket.Api.Controllers.Admin;

/// <summary>Чтение per-tenant журнала мутаций. Запись — автоматическая через
/// <c>OrgAuditInterceptor</c>; этот контроллер только показывает. Доступ —
/// admin'у организации (через permission OrgSettingsManage). SuperAdmin
/// видит всё (через query-filter bypass + IsSuperAdmin).</summary>
[ApiController]
[Authorize]
[Route("api/admin/audit-log")]
public class OrgAuditLogController : ControllerBase
{
    private readonly AppDbContext _db;
    public OrgAuditLogController(AppDbContext db) => _db = db;

    public record AuditRow(
        Guid Id, DateTime CreatedAt,
        Guid? UserId, string? UserName,
        string Action, string EntityType, Guid? EntityId,
        string ChangesJson);

    [HttpGet, RequiresPermission("OrgSettingsManage")]
    public async Task<ActionResult<PagedResult<AuditRow>>> List(
        [FromQuery] PagedRequest req,
        [FromQuery] string? entityType,
        [FromQuery] Guid? entityId,
        [FromQuery] Guid? userId,
        [FromQuery] string? action,
        [FromQuery] DateTime? from,
        [FromQuery] DateTime? to,
        CancellationToken ct)
    {
        var q = _db.OrgAuditLogs.AsNoTracking().AsQueryable();
        if (!string.IsNullOrWhiteSpace(entityType)) q = q.Where(l => l.EntityType == entityType);
        if (entityId is not null) q = q.Where(l => l.EntityId == entityId);
        if (userId is not null) q = q.Where(l => l.UserId == userId);
        if (!string.IsNullOrWhiteSpace(action)) q = q.Where(l => l.Action == action);
        if (from is not null) q = q.Where(l => l.CreatedAt >= from);
        if (to is not null) q = q.Where(l => l.CreatedAt <= to);

        var total = await q.CountAsync(ct);
        var items = await (from l in q.OrderByDescending(l => l.CreatedAt)
                                       .Skip(req.Skip).Take(req.Take)
                           join u in _db.Users.AsNoTracking() on l.UserId equals u.Id into uj
                           from u in uj.DefaultIfEmpty()
                           select new AuditRow(
                               l.Id, l.CreatedAt,
                               l.UserId, u != null ? u.FullName : null,
                               l.Action, l.EntityType, l.EntityId,
                               l.ChangesJson))
            .ToListAsync(ct);

        return new PagedResult<AuditRow> { Items = items, Total = total, Page = req.Page, PageSize = req.Take };
    }
}
