using Microsoft.EntityFrameworkCore;
using OmsorgCore.Application.Abstractions;
using OmsorgCore.Domain.Entities;
using OmsorgCore.Domain.Enums;
using OmsorgCore.Infrastructure.Persistence;

namespace OmsorgCore.Infrastructure.Repositories;

public class AuditLogRepository : IAuditLogRepository
{
    private readonly OmsorgCoreDbContext _db;

    public AuditLogRepository(OmsorgCoreDbContext db)
    {
        _db = db;
    }

    public async Task AddAsync(AuditLogEntry entry, CancellationToken cancellationToken = default)
        => await _db.AuditLogEntries.AddAsync(entry, cancellationToken);

    public async Task<(IReadOnlyList<AuditLogEntry> Items, int TotalCount)> GetPagedAsync(
        string? entityType,
        Guid? entityId,
        Guid? actorUserId,
        AuditEventCategory? category,
        DateTime? fromUtc,
        DateTime? toUtc,
        int page,
        int pageSize,
        CancellationToken cancellationToken = default)
    {
        var query = _db.AuditLogEntries.AsNoTracking().AsQueryable();

        if (!string.IsNullOrWhiteSpace(entityType))
        {
            query = query.Where(e => e.EntityType == entityType);
        }

        if (entityId is not null)
        {
            query = query.Where(e => e.EntityId == entityId);
        }

        if (actorUserId is not null)
        {
            query = query.Where(e => e.ActorUserId == actorUserId);
        }

        if (category is not null)
        {
            query = query.Where(e => e.Category == category);
        }

        if (fromUtc is not null)
        {
            query = query.Where(e => e.OccurredAtUtc >= fromUtc);
        }

        if (toUtc is not null)
        {
            query = query.Where(e => e.OccurredAtUtc <= toUtc);
        }

        var totalCount = await query.CountAsync(cancellationToken);

        var items = await query
            .OrderByDescending(e => e.OccurredAtUtc)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync(cancellationToken);

        return (items, totalCount);
    }

    public Task SaveChangesAsync(CancellationToken cancellationToken = default)
        => _db.SaveChangesAsync(cancellationToken);
}
