using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using AyaNova.Models;
using System.ComponentModel.DataAnnotations;


namespace AyaNova.Api.Controllers
{

    /// <summary>
    /// Server state controller
    /// </summary>
    [ApiController]
    [ApiVersion("8.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    [Produces("application/json")]
    public class ServerStateController : ControllerBase
    {
        private readonly AyContext ct;
        private readonly ILogger<ServerStateController> log;
        private readonly ApiServerState serverState;

        /// <summary>
        /// ctor
        /// </summary>    
        /// <param name="logger"></param>
        /// <param name="apiServerState"></param>
        /// <param name="dbcontext"></param>
        public ServerStateController(ILogger<ServerStateController> logger, ApiServerState apiServerState, AyContext dbcontext)
        {
            ct = dbcontext;
            log = logger;
            serverState = apiServerState;
        }


        /// <summary>
        /// Get server state 
        /// </summary>
        /// <returns>Current server state (Closed, OpsOnly, Open)</returns>
        [HttpGet]
        public ActionResult Get()
        {
            return Ok(ApiOkResponse.Response(new ServerStateModel() { ServerState = serverState.GetState().ToString(), Reason = serverState.Reason }, true));
        }


        /// <summary>
        /// Set server state
        /// Valid parameters:
        /// One of "Closed", "OpsOnly" or "Open"
        /// </summary>
        /// <param name="state">{"NewState":"Closed"}</param>
        /// <returns>NoContent 204</returns>
        [HttpPost]
        [Authorize]
        public async Task<IActionResult> PostServerState([FromBody] ServerStateModel state)
        {
            if (!Authorized.HasModifyRole(HttpContext.Items, AyaType.ServerState))
            {
                return StatusCode(403, new ApiNotAuthorizedResponse());
            }

            if (serverState.IsSystemLocked)//no state change allowed when system locked, must correct the problem first
            {
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
            }

            if (!ModelState.IsValid)
            {
                return BadRequest(new ApiErrorResponse(ModelState));
            }

            ApiServerState.ServerState desiredState;

            if (!Enum.TryParse<ApiServerState.ServerState>(state.ServerState, true, out desiredState))
            {
                return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, "Invalid state -  must be one of \"Closing\", \"Closed\", \"OpsOnly\" or \"Open\""));
            }

            log.LogInformation($"ServerState change request by user {UserNameFromContext.Name(HttpContext.Items)} from current state of \"{serverState.GetState().ToString()}\" to \"{desiredState.ToString()}\"");

            serverState.SetState(desiredState, state.Reason);

            //Log
            await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.ServerState, AyaEvent.ServerStateChange, $"{state.ServerState}-{state.Reason}"), ct);

            return NoContent();
        }


        /// <summary>
        /// Parameter object
        /// </summary>
        public class ServerStateModel
        {
            /// <summary>
            /// One of "Closed", "OpsOnly" or "Open"
            /// </summary>
            /// <returns></returns>
            [Required]
            public string ServerState { get; set; }

            /// <summary>
            /// Reason for server state
            /// </summary>
            /// <returns></returns>
            public string Reason { get; set; }
        }

        //------------


    }
}