using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

/// <summary>
/// SOFA composite scoring: current score and paginated history per encounter.
/// </summary>
[ApiController]
[Route("api/v1/encounters/{encounterId:guid}/sofa")]
[Produces("application/json")]
[AuthorizePermission(ClinicalPermissions.EncountersRead)]
public class SofaController : ControllerBase
{
    private readonly ISofaService _sofa;

    public SofaController(ISofaService sofa) => _sofa = sofa;

    /// <summary>
    /// Returns the latest SOFA score for an encounter, or null data when no score has been computed.
    /// </summary>
    /// <param name="encounterId">Encounter id.</param>
    /// <returns>The SOFA component scores and total, or null.</returns>
    [HttpGet]
    [ProducesResponseType(typeof(ApiResponse<SofaScoreResponse>), StatusCodes.Status200OK)]
    public async Task<IActionResult> Current(Guid encounterId)
    {
        var score = await _sofa.GetCurrentAsync(encounterId);
        if (score is null)
            return Ok(ApiResponse<SofaScoreResponse?>.Ok(null));

        return Ok(ApiResponse<SofaScoreResponse>.Ok(MapResponse(score)));
    }

    /// <summary>
    /// Returns cursor-paginated SOFA score history for an encounter.
    /// </summary>
    /// <param name="encounterId">Encounter id.</param>
    /// <param name="limit">Maximum items per page.</param>
    /// <param name="cursor">Opaque cursor from a previous page.</param>
    /// <returns>A page of SOFA scores with an optional next cursor.</returns>
    [HttpGet("history")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    public async Task<IActionResult> History(
        Guid encounterId,
        [FromQuery] int limit = 20,
        [FromQuery] string? cursor = null)
    {
        var page = await _sofa.GetHistoryAsync(encounterId, limit, cursor);
        return Ok(ApiResponse<object>.Ok(new
        {
            items = page.Items.Select(MapResponse),
            nextCursor = page.NextCursor,
            hasMore = page.HasMore
        }));
    }

    private static SofaScoreResponse MapResponse(SofaScore score)
    {
        SofaStalenessInfo? staleness = null;
        if (!string.IsNullOrEmpty(score.StalenessFlags))
        {
            var flags = JsonSerializer.Deserialize<SofaStalenessFlags>(
                score.StalenessFlags,
                new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            if (flags is not null)
            {
                staleness = new SofaStalenessInfo(
                    flags.StaleComponents, flags.MissingComponents, flags.UsedSpO2Fallback);
            }
        }

        return new SofaScoreResponse(
            score.TotalScore,
            score.RespiratoryScore, score.CoagulationScore, score.LiverScore,
            score.CardiovascularScore, score.CnsScore, score.RenalScore,
            score.IsBaseline, score.DeltaFromBaseline,
            staleness, score.CalculatedAt);
    }
}