using System.Reflection;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using StartupHelpers;
using Swashbuckle.AspNetCore.Annotations;

namespace Api.Controllers
{
    /// <summary>
    /// Controller that exposes simple health and readiness endpoints for the API.
    /// Routes are prefixed with "api/health".
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    // Enables only the "FrontendOnly" CORS policy so browser requests from the frontend are allowed.
    [EnableCors("FrontendOnly")]
    public sealed class HealthController : ControllerBase
    {
        /// <summary>
        /// Returns the deployed API version baked into the assembly at build time.
        /// The version format is <c>1.0.0-build.{yyyyMMddHHmmss}</c> as defined in <c>api.csproj</c>.
        /// Used by the web frontend to display the running build in the page footer.
        /// </summary>
        /// <returns>200 OK with JSON payload: <c>{ "version": "1.0.0-build.20250522103045" }</c>.</returns>
        // GET api/health/version
        [HttpGet("version")]
        [SwaggerOperation(Summary = "API version", Description = "Returns the deployed API assembly version.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Version returned")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public IActionResult Version() =>
            Ok(new { version = StartupExtensions.GetApplicationVersion(Assembly.GetExecutingAssembly()) });

        /// <summary>
        /// Liveness probe.
        /// Indicates whether the process is running. Used by orchestration systems to confirm the process is alive.
        /// </summary>
        /// <returns>
        /// 200 OK with JSON payload: { "status": "alive" } when the process is running.
        /// </returns>
        // GET api/health/live
        [HttpGet("live")]
        [SwaggerOperation(Summary = "Liveness probe", Description = "Returns whether the API process is alive.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Service is alive")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public IActionResult Live() => Ok(new { status = "alive" });

        /// <summary>
        /// Basic health check endpoint.
        /// Returns overall status and the current server time in UTC.
        /// </summary>
        /// <returns>
        /// 200 OK with JSON payload: { "status": "ok", "time": &lt;UTC time&gt; }.
        /// </returns>
        // GET api/health
        [HttpGet]
        [SwaggerOperation(Summary = "Health check", Description = "Returns overall health status and current UTC time.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Health check succeeded")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });

        /// <summary>
        /// Echo endpoint.
        /// Returns the received JSON payload unchanged. Useful for testing request/response plumbing.
        /// </summary>
        /// <param name="payload">Arbitrary JSON from the request body. The endpoint returns the same object.</param>
        /// <returns>200 OK with the same JSON payload provided in the request body.</returns>
        // POST api/health/echo
        [HttpPost("echo")]
        [SwaggerOperation(Summary = "Echo payload", Description = "Returns the same JSON payload received in the request body.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Payload echoed successfully")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public IActionResult Echo(object payload) => Ok(payload);

        /// <summary>
        /// Readiness probe.
        /// Indicates whether the service is ready to accept traffic. Typically checks downstream dependencies.
        /// </summary>
        /// <returns>
        /// 200 OK with JSON { "status": "ready" } when ready;
        /// 503 Service Unavailable with JSON { "status": "not_ready" } when not ready.
        /// </returns>
        // GET api/health/ready
        [HttpGet("ready")]
        [SwaggerOperation(Summary = "Readiness probe", Description = "Returns whether the service is ready to accept traffic.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Service is ready")]
        [SwaggerResponse(StatusCodes.Status503ServiceUnavailable, "Service is not ready")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
        public IActionResult Ready()
        {
            var ready = true;

            return ready
                ? Ok(new { status = "ready" })
                : StatusCode(503, new { status = "not_ready" });
        }
    }
}