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


/// <summary>
/// Elasticsearch-backed analytics queries for population, trends, alerts, and patient search.
/// </summary>
[ApiController]
[Route("api/v1/analytics")]
[Produces("application/json")]
[AuthorizePermission(ClinicalPermissions.AnalyticsRead)]
public class AnalyticsController : ControllerBase
{
    private readonly IAnalyticsService _analytics;

    public AnalyticsController(IAnalyticsService analytics) => _analytics = analytics;

    /// <summary>
    /// Counts distinct patients whose observations for a code exceed or fall below a threshold in a time window.
    /// </summary>
    /// <param name="code">Observation code (e.g. HEART_RATE).</param>
    /// <param name="threshold">Numeric threshold value.</param>
    /// <param name="direction">above or below.</param>
    /// <param name="from">Optional start of recorded-at range.</param>
    /// <param name="to">Optional end of recorded-at range.</param>
    /// <returns>Cardinality of unique patients matching the criteria.</returns>
    [HttpGet("population")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Population(
        [FromQuery] string? code,
        [FromQuery] decimal threshold,
        [FromQuery] string direction,  // "above" | "below"
        [FromQuery] DateTimeOffset? from,
        [FromQuery] DateTimeOffset? to)
    {
        if (string.IsNullOrWhiteSpace(code))
            return BadRequest(ApiResponse<object>.Fail(400, "code is required.", "MISSING_CODE"));

        var result = await _analytics.GetPopulationAsync(code, threshold, direction, from, to);
        return Ok(ApiResponse<object>.Ok(result));
    }

    /// <summary>
    /// Returns hourly observation volume for an encounter and observation code.
    /// </summary>
    /// <param name="encounterId">Encounter id.</param>
    /// <param name="code">Observation code.</param>
    /// <param name="from">Optional start of recorded-at range.</param>
    /// <param name="to">Optional end of recorded-at range.</param>
    /// <returns>Hourly trend buckets with document counts.</returns>
    [HttpGet("observations/trend")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> ObservationTrend(
        [FromQuery] Guid encounterId,
        [FromQuery] string code,
        [FromQuery] DateTimeOffset? from,
        [FromQuery] DateTimeOffset? to)
    {
        var result = await _analytics.GetObservationTrendAsync(encounterId, code, from, to);
        return Ok(ApiResponse<object>.Ok(result));
    }

    /// <summary>
    /// Summarizes alert volume by department over a time window.
    /// </summary>
    /// <param name="severity">Optional severity filter.</param>
    /// <param name="department">Optional department filter.</param>
    /// <param name="from">Optional start of triggered-at range.</param>
    /// <param name="to">Optional end of triggered-at range.</param>
    /// <returns>Department-level counts (severity breakdown omitted in current implementation).</returns>
    [HttpGet("alerts/summary")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> AlertSummary(
        [FromQuery] string? severity,
        [FromQuery] string? department,
        [FromQuery] DateTimeOffset? from,
        [FromQuery] DateTimeOffset? to)
    {
        var result = await _analytics.GetAlertSummaryAsync(severity, department, from, to);
        return Ok(ApiResponse<object>.Ok(result));
    }

    /// <summary>
    /// Searches patient/encounter documents by MRN, name, department, or status.
    /// </summary>
    /// <param name="q">Free-text query (MRN, name, or department).</param>
    /// <param name="department">Optional department filter.</param>
    /// <param name="status">Optional encounter status filter.</param>
    /// <param name="page">Page number (0-based).</param>
    /// <param name="pageSize">Results per page.</param>
    /// <returns>Matching patient/encounter documents.</returns>
    [HttpGet("patients")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> PatientSearch(
        [FromQuery] string? q,
        [FromQuery] string? department,
        [FromQuery] string? status,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        var result = await _analytics.SearchPatientsAsync(q, department, status, page, pageSize);
        return Ok(ApiResponse<object>.Ok(result));
    }
}
