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


namespace AyaNova.Api.Controllers
{

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


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




        /// <summary>
        /// Get License info
        /// 
        /// Required roles:
        /// AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminFull | 
        /// AuthorizationRoles.BizAdminLimited | AuthorizationRoles.OpsAdminLimited
        /// </summary>       
        /// <returns>Information about the currently installed license in AyaNova</returns>
        [HttpGet()]
        public ActionResult GetLicenseInfo()
        {
            //Open or opsOnly and user is opsadminfull or opsadminlimited
            if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull | AuthorizationRoles.OpsAdminLimited)))
            {
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
            }

            if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.License))
            {
                return StatusCode(403, new ApiNotAuthorizedResponse());
            }

            var ret = AyaNova.Core.License.LicenseInfoAsJson;

            return Ok(ApiOkResponse.Response(ret, true));
        }




        /// <summary>
        /// Fetch license
        /// 
        /// Posting to this route causes AyaNova to attempt to refresh it's license 
        /// from the AyaNova license server
        /// 
        /// Required roles: 
        /// AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminFull
        /// </summary>    
        /// <returns>On success returns information about the currently installed license in AyaNova</returns>
        [HttpPost]
        public ActionResult FetchLicense()
        {
            //Open or opsOnly and user is opsadminfull
            if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull)))
            {
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
            }

            if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.License))
            {
                return StatusCode(403, new ApiNotAuthorizedResponse());
            }

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

            try
            {
                AyaNova.Core.License.Fetch(serverState, ct, log);
            }
            catch (Exception ex)
            {
                Exception rootex = ex;
                while (rootex.InnerException != null)
                {
                    rootex = rootex.InnerException;
                }


                if (rootex.Message.Contains("E1020"))
                {
                    return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "LICENSE_KEY", rootex.Message));
                }
                else
                {
                    throw ex;
                }

            }
            var ret = AyaNova.Core.License.LicenseInfoAsJson;
            //Log
            EventLogProcessor.LogEventToDatabase(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct);
         
            return Ok(ApiOkResponse.Response(ret, true));
        }



        /// <summary>
        /// Request trial license
        /// 
        /// Posting to this route causes AyaNova to request a trial license key from the AyaNova license server
        /// Database must be empty and unlicensed or trial license
        /// 
        /// Required roles:
        /// [OpsFull, BizAdminFull]
        /// 
        /// </summary>
        /// <param name="requestData"></param>
        /// <returns>HTTP 204 No Content result code on success or fail code with explanation</returns>
        [HttpPost("trial")]
        public ActionResult RequestTrial([FromBody] dtoTrialRequestData requestData)
        {
            //Open or opsOnly and user is opsadminfull
            if (!serverState.IsOpenOrOpsOnly || (serverState.IsOpsOnly && !Authorized.HasAnyRole(HttpContext.Items, AuthorizationRoles.OpsAdminFull)))
            {
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));
            }

            if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.License))
            {
                return StatusCode(403, new ApiNotAuthorizedResponse());
            }

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

            if (!AyaNova.Util.DbUtil.DBIsEmpty(ct, log))
            {
                return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Only an empty AyaNova database can request a trial key. Erase the database to proceed with a new trial."));
            }

            if (!AyaNova.Core.License.ActiveKey.IsEmpty && !AyaNova.Core.License.ActiveKey.TrialLicense)
            {
                return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "There is an active registered license. Only an unlicensed or trial license database can request a trial key."));
            }

            //Send the request to RockFish here (or at least start the job to do it in which case return Accepted instead of no content and update comment above)
            var ret = Core.License.RequestTrial(requestData.EmailAddress, requestData.RegisteredTo, log);

            //Log
            EventLogProcessor.LogEventToDatabase(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct);
                       
            return Ok(ApiOkResponse.Response(ret, true));
        }

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

        public class dtoTrialRequestData
        {
            [System.ComponentModel.DataAnnotations.Required]
            public string RegisteredTo { get; set; }
            [System.ComponentModel.DataAnnotations.Required, System.ComponentModel.DataAnnotations.EmailAddress]
            public string EmailAddress { get; set; }

        }




    }//eoc
}//eons