using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; /// /// Patient registration, search, and encounter opening. /// [ApiController] [Route("api/v1/patients")] [Produces("application/json")] [Authorize] public class PatientsController : ControllerBase { private readonly IPatientService _patients; public PatientsController(IPatientService patients) => _patients = patients; /// /// Registers a new patient and assigns a system-generated MRN. /// /// Patient demographics. /// The created patient record. [HttpPost] [AuthorizePermission(ClinicalPermissions.PatientsWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status201Created)] public async Task Register([FromBody] RegisterPatientRequest req) { var patient = await _patients.RegisterAsync(req); return StatusCode(201, ApiResponse.Created(patient)); } /// /// Lists patients with optional MRN or name search and pagination. /// /// MRN (exact) or name substring (ILIKE). /// Page number (1-based). /// Results per page. /// A paginated list of patients. [HttpGet] [AuthorizePermission(ClinicalPermissions.PatientsRead)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] public async Task List([FromQuery] string? q, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { var result = await _patients.ListAsync(q, page, pageSize); return Ok(ApiResponse.Ok(new { items = result.Items, page = result.Page, pageSize = result.PageSize, totalCount = result.TotalCount, totalPages = result.TotalPages })); } /// /// Gets a patient by id, including active encounters. /// /// Patient id. /// The patient record. [HttpGet("{id:guid}")] [AuthorizePermission(ClinicalPermissions.PatientsRead)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] public async Task Get(Guid id) { var patient = await _patients.GetByIdAsync(id); return Ok(ApiResponse.Ok(patient)); } /// /// Opens a new active encounter for the patient. /// /// Patient id. /// Encounter type, department, and attending physician. /// The created encounter. [HttpPost("{id:guid}/encounters")] [AuthorizePermission(ClinicalPermissions.EncountersWrite)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status201Created)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status409Conflict)] public async Task OpenEncounter(Guid id, [FromBody] OpenEncounterRequest req) { var encounter = await _patients.OpenEncounterAsync(id, req); return StatusCode(201, ApiResponse.Created(encounter)); } }