using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; /// /// PHI access log query for compliance (Admin / Compliance). /// [ApiController] [Route("api/v1/phi-access-logs")] [Produces("application/json")] [AuthorizePermission(ClinicalPermissions.AuditRead)] public class PhiAccessLogsController : ControllerBase { private readonly AppDbContext _db; public PhiAccessLogsController(AppDbContext db) => _db = db; /// Query PHI access logs — who viewed which patient records. [HttpGet] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] public async Task List( [FromQuery] Guid? patientId, [FromQuery] Guid? userId, [FromQuery] string? accessType, [FromQuery] DateTimeOffset? from, [FromQuery] DateTimeOffset? to, [FromQuery] int page = 1, [FromQuery] int pageSize = 50) { pageSize = Math.Clamp(pageSize, 1, 100); var query = _db.PhiAccessLogs.AsNoTracking().AsQueryable(); if (patientId.HasValue) query = query.Where(l => l.PatientId == patientId); if (userId.HasValue) query = query.Where(l => l.UserId == userId); if (!string.IsNullOrEmpty(accessType)) query = query.Where(l => l.AccessType.ToDbString() == accessType); if (from.HasValue) query = query.Where(l => l.AccessedAt >= from); if (to.HasValue) query = query.Where(l => l.AccessedAt <= to); var total = await query.CountAsync(); var items = await query .OrderByDescending(l => l.AccessedAt) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); return Ok(ApiResponse.Ok(new { items, page, pageSize, totalCount = total, totalPages = (int)Math.Ceiling(total / (double)pageSize) })); } /// Access history for a specific patient — common compliance query. /// Patient id. /// Page number (1-based). /// Results per page. /// A paginated list of PHI access events for the patient. [HttpGet("patients/{patientId:guid}")] [AuthorizePermission(ClinicalPermissions.PatientsRead)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] public async Task ForPatient( Guid patientId, [FromQuery] int page = 1, [FromQuery] int pageSize = 50) { pageSize = Math.Clamp(pageSize, 1, 100); var query = _db.PhiAccessLogs.AsNoTracking() .Where(l => l.PatientId == patientId); var total = await query.CountAsync(); var items = await query .OrderByDescending(l => l.AccessedAt) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); return Ok(ApiResponse.Ok(new { items, page, pageSize, totalCount = total, totalPages = (int)Math.Ceiling(total / (double)pageSize) })); } }