using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;


/// <summary>
/// Encounter retrieval, status transitions, and clinical timeline.
/// </summary>
[ApiController]
[Route("api/v1/encounters")]
[Produces("application/json")]
[Authorize]
public class EncountersController : ControllerBase
{
    private readonly IEncounterService _encounters;
    private readonly IDischargeSummaryService _dischargeSummary;

    public EncountersController(
        IEncounterService encounters,
        IDischargeSummaryService dischargeSummary)
    {
        _encounters = encounters;
        _dischargeSummary = dischargeSummary;
    }

    /// <summary>
    /// Lists encounters for ward dashboards with denormalized clinical summary fields.
    /// </summary>
    /// <param name="status">Optional status filter (DB literal, e.g. ACTIVE).</param>
    /// <param name="department">Optional department filter (DB literal, e.g. ICU).</param>
    /// <param name="page">Page number (1-based).</param>
    /// <param name="pageSize">Results per page.</param>
    [HttpGet]
    [AuthorizePermission(ClinicalPermissions.EncountersRead)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> List(
        [FromQuery] string? status,
        [FromQuery] string? department,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        EncounterStatus? parsedStatus = null;
        if (!string.IsNullOrEmpty(status))
        {
            try
            {
                parsedStatus = EncounterStatusExtensions.FromDbString(status);
            }
            catch (ArgumentOutOfRangeException)
            {
                return BadRequest(ApiResponse<object>.Fail(400, "Invalid status filter.", "INVALID_STATUS"));
            }
        }

        Department? parsedDepartment = null;
        if (!string.IsNullOrEmpty(department))
        {
            try
            {
                parsedDepartment = DepartmentExtensions.FromDbString(department);
            }
            catch (ArgumentOutOfRangeException)
            {
                return BadRequest(ApiResponse<object>.Fail(400, "Invalid department filter.", "INVALID_DEPARTMENT"));
            }
        }

        var result = await _encounters.ListAsync(parsedStatus, parsedDepartment, page, pageSize);
        return Ok(ApiResponse<object>.Ok(new
        {
            items = result.Items,
            page = result.Page,
            pageSize = result.PageSize,
            totalCount = result.TotalCount,
            totalPages = result.TotalPages
        }));
    }

    /// <summary>
    /// Gets an encounter with patient, recent observations, and open alerts.
    /// </summary>
    /// <param name="id">Encounter id.</param>
    /// <returns>The encounter with related data.</returns>
    [HttpGet("{id:guid}")]
    [AuthorizePermission(ClinicalPermissions.EncountersRead)]
    [ProducesResponseType(typeof(ApiResponse<Encounter>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Get(Guid id)
    {
        var encounter = await _encounters.GetByIdAsync(id);
        return Ok(ApiResponse<Encounter>.Ok(encounter));
    }

    /// <summary>
    /// Transitions an encounter to a new status via the encounter state machine.
    /// </summary>
    /// <param name="id">Encounter id.</param>
    /// <param name="req">Target status.</param>
    /// <returns>The encounter id and new status.</returns>
    [HttpPatch("{id:guid}/status")]
    [AuthorizePermission(ClinicalPermissions.EncountersWrite)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<IActionResult> TransitionStatus(Guid id, [FromBody] TransitionStatusRequest req)
    {
        var result = await _encounters.TransitionStatusAsync(id, req.Status, req.DischargeDiagnosis);
        return Ok(ApiResponse<object>.Ok(new { encounterId = result.EncounterId, newStatus = result.NewStatus, dischargeDiagnosis = req.DischargeDiagnosis }));
    }

    /// <summary>
    /// Returns a merged chronological timeline of observations and alerts for an encounter.
    /// </summary>
    /// <param name="id">Encounter id.</param>
    /// <returns>Ordered timeline events.</returns>
    [HttpGet("{id:guid}/timeline")]
    [AuthorizePermission(ClinicalPermissions.EncountersRead)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Timeline(Guid id)
    {
        var timeline = await _encounters.GetTimelineAsync(id);
        return Ok(ApiResponse<object>.Ok(timeline));
    }

    /// <summary>
    /// Returns discharge summary availability for a discharged encounter.
    /// </summary>
    [HttpGet("{id:guid}/discharge-summary")]
    [AuthorizePermission(ClinicalPermissions.EncountersRead)]
    [ProducesResponseType(typeof(ApiResponse<DischargeSummaryInfo>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetDischargeSummary(Guid id)
    {
        var info = await _dischargeSummary.GetInfoAsync(id);
        return Ok(ApiResponse<DischargeSummaryInfo>.Ok(info));
    }

    /// <summary>
    /// Downloads the generated discharge summary document.
    /// </summary>
    [HttpGet("{id:guid}/discharge-summary/content")]
    [AuthorizePermission(ClinicalPermissions.EncountersRead)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<IActionResult> DownloadDischargeSummary(Guid id)
    {
        var content = await _dischargeSummary.GetContentAsync(id);
        return File(content.Stream, content.ContentType, content.FileName);
    }
}
