using adas_core.Application.Services.Interfaces;
using adas_core.Authentication.Attributes;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.DTO;
using adas_core.Logging;
using Microsoft.AspNetCore.Mvc;

namespace adas_core.Controllers;

/// <summary>
/// Serves as the API endpoint container for managing medical diagnosis resources, exposing operations under the <c>diagnosis</c> route.
/// </summary>
/// <remarks>
/// The controller is bound to the <c>diagnosis</c> URI path through <see cref="RouteAttribute"/> and enabled with Web API conventions by <see cref="ApiControllerAttribute"/>, while inheriting base MVC functionality from <see cref="ControllerBase"/>.
/// </remarks>
/// <!-- aidoc:v1 sig=f08421f -->
[Route("diagnosis")]
[ApiController]
public class DiagnosisController : ControllerBase
{
    private readonly IDiagnosisService _diagnosisService;

    /// <summary>
    /// Initializes a new instance of the <see cref="DiagnosisController"/> class, establishing a logging trace identifier via <see cref="LogExecutionContext.TrySetTraceIdentifier"/> and storing the injected <paramref name="diagnosisService"/> dependency used to handle diagnosis-related operations.
    /// </summary>
    /// <param name="diagnosisService">The <see cref="IDiagnosisService"/> instance used by the controller to perform diagnosis operations.</param>
    /// <!-- aidoc:v1 sig=187a652 body=5aa11c1 -->
    public DiagnosisController(IDiagnosisService diagnosisService)
    {
        LogExecutionContext.TrySetTraceIdentifier(Guid.NewGuid().ToString(), true);

        _diagnosisService = diagnosisService;
    }

    /// <summary>
    /// Processes an ORU_R01 HL7-style request from a diagnosis payload, persisting it either synchronously or asynchronously depending on the caller's wait-for-result preference.
    /// </summary>
    /// <param name="diagnosisDto">The diagnosis payload received in the request body, containing the patient number, location, observation data, observations, diagnosis text, message timestamp, and a flag indicating whether the caller wants to wait for the result.</param>
    /// <returns>An <see cref="IActionResult"/> that returns an HTTP 200 OK response when the request is accepted for processing.</returns>
    /// <!-- aidoc:v1 sig=8c96f8f body=98d5d44 -->
    [HttpPost]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public IActionResult ProcessRequest([FromBody] DiagnosisDto diagnosisDto)
    {
        var request = new ApiRequest
        {
            TraceId = Guid.NewGuid().ToString(),
            Type = "ORU_R01",
            PatientNumber = diagnosisDto.PatientNumber,
            Location = diagnosisDto.Location,
            ObservationData = diagnosisDto.ObservationData,
            Observations = diagnosisDto.Observations,
            Diagnosis = diagnosisDto.Diagnosis,
            MessageTime = diagnosisDto.MessageTime,
            WaitResult = diagnosisDto.WaitResult
        };

        if (request.WaitResult)
            _diagnosisService.SaveRequest(request);
        else
            _diagnosisService.SaveRequestAsync(request);

        return Ok();
    }
}