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


/// <summary>
/// Clinical alert listing, acknowledgment, and resolution.
/// </summary>
[ApiController]
[Produces("application/json")]
[Authorize]
public class AlertsController : ControllerBase
{
    private readonly IAlertService _alerts;

    public AlertsController(IAlertService alerts) => _alerts = alerts;

    /// <summary>
    /// Lists alerts for a single encounter with optional status filter.
    /// </summary>
    /// <param name="encounterId">Encounter id.</param>
    /// <param name="status">Optional status filter (DB literal, e.g. OPEN).</param>
    /// <param name="page">Page number (1-based).</param>
    /// <param name="pageSize">Results per page.</param>
    /// <returns>A paginated list of alerts for the encounter.</returns>
    [HttpGet("api/v1/encounters/{encounterId:guid}/alerts")]
    [AuthorizePermission(ClinicalPermissions.AlertsRead)]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<AlertResponse>>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ListByEncounter(
        Guid encounterId,
        [FromQuery] string? status,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        AlertStatus? parsedStatus = null;
        if (!string.IsNullOrEmpty(status))
        {
            try
            {
                parsedStatus = AlertStatusExtensions.FromDbString(status);
            }
            catch (ArgumentOutOfRangeException)
            {
                return BadRequest(ApiResponse<object>.Fail(400, "Invalid status filter.", "INVALID_STATUS"));
            }
        }

        var result = await _alerts.ListByEncounterAsync(encounterId, parsedStatus, page, pageSize);
        return Ok(ApiResponse<PagedResult<AlertResponse>>.Ok(result));
    }

    /// <summary>
    /// Lists alerts across all encounters with optional status, severity, and department filters.
    /// </summary>
    /// <param name="status">Optional status filter (DB literal, e.g. OPEN).</param>
    /// <param name="severity">Optional severity filter (DB literal, e.g. CRITICAL).</param>
    /// <param name="department">Optional department filter.</param>
    /// <param name="page">Page number (1-based).</param>
    /// <param name="pageSize">Results per page.</param>
    /// <returns>A paginated list of alerts.</returns>
    [HttpGet("api/v1/alerts")]
    [AuthorizePermission(ClinicalPermissions.AlertsRead)]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<AlertResponse>>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> ListGlobal(
        [FromQuery] string? status,
        [FromQuery] string? severity,
        [FromQuery] string? department,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        AlertStatus? parsedStatus = null;
        if (!string.IsNullOrEmpty(status))
        {
            try
            {
                parsedStatus = AlertStatusExtensions.FromDbString(status);
            }
            catch (ArgumentOutOfRangeException)
            {
                return BadRequest(ApiResponse<object>.Fail(400, "Invalid status filter.", "INVALID_STATUS"));
            }
        }

        AlertSeverity? parsedSeverity = null;
        if (!string.IsNullOrEmpty(severity))
        {
            try
            {
                parsedSeverity = AlertSeverityExtensions.FromDbString(severity);
            }
            catch (ArgumentOutOfRangeException)
            {
                return BadRequest(ApiResponse<object>.Fail(400, "Invalid severity filter.", "INVALID_SEVERITY"));
            }
        }

        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 _alerts.ListGlobalAsync(parsedStatus, parsedSeverity, parsedDepartment, page, pageSize);
        return Ok(ApiResponse<PagedResult<AlertResponse>>.Ok(result));
    }

    /// <summary>
    /// Gets a single alert by id, including its encounter.
    /// </summary>
    /// <param name="id">Alert id.</param>
    /// <returns>The alert record.</returns>
    [HttpGet("api/v1/alerts/{id:guid}")]
    [AuthorizePermission(ClinicalPermissions.AlertsRead)]
    [ProducesResponseType(typeof(ApiResponse<AlertResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Get(Guid id)
    {
        var alert = await _alerts.GetByIdAsync(id);
        return Ok(ApiResponse<AlertResponse>.Ok(alert));
    }

    /// <summary>
    /// Acknowledges an open or escalated alert and emits an outbox event for downstream consumers.
    /// </summary>
    /// <param name="id">Alert id.</param>
    /// <param name="req">Optional acknowledgment note.</param>
    /// <returns>The updated alert.</returns>
    [HttpPost("api/v1/alerts/{id:guid}/acknowledge")]
    [AuthorizePermission(ClinicalPermissions.AlertsAcknowledge)]
    [ProducesResponseType(typeof(ApiResponse<AlertResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<IActionResult> Acknowledge(Guid id, [FromBody] AcknowledgeAlertRequest req)
    {
        var alert = await _alerts.AcknowledgeAsync(id, req);
        return Ok(ApiResponse<AlertResponse>.Ok(alert));
    }

    /// <summary>
    /// Resolves an acknowledged alert.
    /// </summary>
    /// <param name="id">Alert id.</param>
    /// <returns>The updated alert.</returns>
    [HttpPost("api/v1/alerts/{id:guid}/resolve")]
    [AuthorizePermission(ClinicalPermissions.AlertsResolve)]
    [ProducesResponseType(typeof(ApiResponse<AlertResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<IActionResult> Resolve(Guid id)
    {
        var alert = await _alerts.ResolveAsync(id);
        return Ok(ApiResponse<AlertResponse>.Ok(alert));
    }

    /// <summary>
    /// Submits clinician feedback for an acknowledged or resolved alert.
    /// One submission per user per alert.
    /// </summary>
    [HttpPost("api/v1/alerts/{id:guid}/feedback")]
    [AuthorizePermission(ClinicalPermissions.AlertsFeedback)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status201Created)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status409Conflict)]
    public async Task<IActionResult> SubmitFeedback(
        Guid id, [FromBody] SubmitAlertFeedbackRequest req)
    {
        var feedback = await _alerts.SubmitFeedbackAsync(id, req.FeedbackType, req.Comment);
        return Created(
            $"/api/v1/alerts/{id}/feedback/{feedback.Id}",
            ApiResponse<object>.Ok(new
            {
                id = feedback.Id,
                alertId = feedback.AlertId,
                feedbackType = feedback.FeedbackType.ToString(),
                comment = feedback.Comment,
                createdAt = feedback.CreatedAt
            }));
    }
}
