using adas_core.Application.Exceptions;
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.Domain.Models.Filter;
using adas_core.Domain.Models.Observations;
using adas_core.Logging;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;

namespace adas_core.Controllers;

[Route("observations")]
[ApiController]
public class ObservationController : ControllerBase
{
    //private readonly IConfigObservationService _configObservation;
    private readonly IObservationService _observationService;
    private readonly IPatientService _patientService;


    public ObservationController(IObservationService observationService, IPatientService patientService)
    {
        LogExecutionContext.TrySetTraceIdentifier(Guid.NewGuid().ToString(), true);

        _observationService = observationService;

        _patientService = patientService;
    }


    [HttpPost]
    [Route("")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthAdmin)]
    public IActionResult ProcessRequest([FromBody] ObservationDto observationDto)
    {
        var request = new ApiRequest
        {
            TraceId = Guid.NewGuid().ToString(),
            Type = "ORU_R01",
            PatientNumber = observationDto.PatientNumber,
            Location = observationDto.Location,
            ObservationData = observationDto.ObservationData,
            Observations = observationDto.Observations,
            MessageTime = observationDto.MessageTime,
            WaitResult = observationDto.WaitResult
        };


        if (request.WaitResult) _observationService.SaveRequest(request);

        else _observationService.SaveRequestAsync(request);
        return NoContent();
    }

    [HttpPost]
    [Route("NurseObservations")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthAdmin)]
    public IActionResult ProcessRequestObsNurse([FromBody] ObservationDto observationDto)
    {
        //if (request == null) return BadRequest("Request is null");
        var request = new ApiRequest
        {
            TraceId = Guid.NewGuid().ToString(),
            Type = "ORU_R01",
            PatientNumber = observationDto.PatientNumber,
            Location = observationDto.Location,
            ObservationData = observationDto.ObservationData,
            Observations = observationDto.Observations,
            MessageTime = observationDto.MessageTime,
            WaitResult = observationDto.WaitResult
        };

        _observationService.SaveRequestNurseObsAsync(request);
        return NoContent();
    }

    // TESTING: Dejar comentado al terminar las pruebas
    [HttpPost]
    [Route("apiRequest")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthAdmin)]
    public IActionResult ProcessRequest([FromBody] ApiRequest apiRequest)
    {
        //if (request == null) return BadRequest("Request is null");

        if (apiRequest.WaitResult) _observationService.SaveRequest(apiRequest);

        else _observationService.SaveRequestAsync(apiRequest);
        return Ok();
    }

    [HttpPost("expired")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public IActionResult ExpireAllExpired()
    {
        _observationService.ExpireObservations();
        return Ok();
    }


    [HttpPost("paginated")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> GetPaginatedObservations([FromBody] PaginationFilter request)
    {
        if (request == null) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestMissingParameters);
        var result = await _observationService.GetPaginatedObservations(request);
        return Ok(result);
    }

    [HttpGet]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> GetObservations([FromBody] ObservationsRequest request)
    {
        if (request.PatientNumber == null)
            throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestMissingParameters);

        var archivedObservation = false;
        var patient = await _patientService.FindByPatientNumber(request.PatientNumber);
        if (patient == null)
        {
            archivedObservation = true;
            patient = await _patientService.FindByPatientNumberArchived(request.PatientNumber);
        }

        if (patient == null) throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
        //if (request.ObservationNames?.Count == 0) return BadRequest("The request need almost one type");

        return Ok(await _observationService.FindAllBetweenDates(patient.Id, request.StartTime, request.EndTime,
            request.ObservationNames, archivedObservation));
    }

    [HttpPost("{patientId}/force-news/{value}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    [PermissionAuthorize("Source", "DisplayId")]
    public async Task<IActionResult> ForceNews(string patientid, string value)
    {
        var parsed = ObjectId.TryParse(patientid, out var paObjectId);
        if (!parsed) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        if (!int.TryParse(value, out _)) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
        var patient = await _patientService.FindById(paObjectId);

        var newObs = new PatientObservation
        {
            Name = "NEWS",
            CodingSystem = "ADAS",
            Expires = 15,
            Value = value,
            PatientId = patient!.Id,
            Time = DateTime.Now
        };
        await _observationService.InsertObservation(newObs);

        return Ok();
    }
}