using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using Sockeye.Models;
using Sockeye.Biz;
using Sockeye.Api.ControllerHelpers;
using System.ComponentModel.DataAnnotations;

namespace Sockeye.Api.Controllers
{
    [Route("rvr")]//v8 fetch license route
    [Produces("application/json")]
    public class RvrController : ControllerBase
    {

        private readonly AyContext ct;
        private readonly ILogger<RvrController> log;
        private readonly ApiServerState serverState;

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

        public class dtoRequest
        {
            [Required]
            public string DbId { get; set; }
            public bool Perpetual { get; set; } = true;//not required and default true to not break any older beta testers out there, can set to required in future
            [Required, EmailAddress]
            public string Email { get; set; }
            [Required]
            public string Company { get; set; }
            [Required]
            public string Contact { get; set; }
        }

#if (DEBUG)
        private const string LICENSE_SERVER_URL = "http://localhost:3001/";
        public const string SUPPORT_EMAIL = "cardjohn@ayanova.com";
#else
        private const string LICENSE_SERVER_URL = "https://rockfish.ayanova.com/";
        public const string SUPPORT_EMAIL="support@ayanova.com";
#endif

        //#########################################################
        //REQUEST TRIAL ROUTE CALLED FROM RAVEN
        //#########################################################
        [HttpPost]
        public async Task<IActionResult> Post([FromBody] dtoRequest r)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

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

            // if (r.DbId == Guid.Empty)
            if (string.IsNullOrWhiteSpace(r.DbId))
            {
                return BadRequest("E1000 - DBId invalid");
            }

            //can't do this if there is a purchased license with this dbid already
            if (await ct.License.Where(z => z.DbId == r.DbId).AnyAsync())
            {
                return BadRequest("E1000 - Can't trial; there is already a purchased license issued for this database Id");
            }

            //can't do this if there is a trial request already pending
            if (await ct.TrialLicenseRequest.Where(z => z.DbId == r.DbId
            && z.Status != Biz.TrialRequestStatus.Approved
            && z.Status != Biz.TrialRequestStatus.Rejected).AnyAsync())
            {
                return Ok("Request awaiting approval");
            }


            //Everything seems to be in order, save the request and return ok
            var newObject = new TrialLicenseRequest();
            newObject.Email = r.Email;
            newObject.DbId = r.DbId;
            newObject.CompanyName = r.Company;
            newObject.ContactName = r.Contact;
            newObject.PGroup = r.Perpetual ? Biz.ProductGroup.RavenPerpetual : Biz.ProductGroup.RavenSubscription;

            TrialLicenseRequestBiz biz = TrialLicenseRequestBiz.GetBiz(ct);
            TrialLicenseRequest o = await biz.CreateAsync(newObject);
            if (o == null)
            {
                 var msg = ($"Unexpected error (code SE-444 was returned to customer) processing a new trial license request:{biz.GetErrorsAsString}");
                log.LogError(msg);
                await NotifyEventHelper.AddOpsProblemEvent(msg);
                return BadRequest($"E1000 - Error processing request code SE-444 contact support");//don't want to leak any info so need to check sockeye log if get this error
            }
            else
                return Accepted();
        }

        //### CUSTOMER ROUTE CALLED FROM CUSTOMER BROWSER / EMAIL ####
        [HttpGet("verify/{code}")]
        public async Task<IActionResult> GetVerify([FromRoute] string code)
        {
            if (!serverState.IsOpen)
                return new ContentResult
                {
                    ContentType = "text/html",
                    StatusCode = 503,
                    Content = "<html><body><h4>Service temporarily unavailable</h4><p>This service is temporarily down for maintenance please try again shortly.</p></body></html>"
                };


            //is there a valid trial request
            var req = await ct.TrialLicenseRequest.AsNoTracking().Where(z => z.EmailConfirmCode == code && z.Status == TrialRequestStatus.AwaitingEmailValidation).FirstOrDefaultAsync();
            if (req == null)
            {
                return new ContentResult
                {
                    ContentType = "text/html",
                    StatusCode = 200,
                    Content = "<html><body><h4>Request not found</h4><p>There was no evaluation request associated with this verification code or it was already validated.</p></body></html>"
                };
            }

            TrialLicenseRequestBiz biz = TrialLicenseRequestBiz.GetBiz(ct);
            var tlr = await biz.GetAsync(req.Id);
            if (tlr == null)
            {
                //this should never happen unless maybe it was *just* validated a moment after this is repeat called?!
                return new ContentResult
                {
                    ContentType = "text/html",
                    StatusCode = 200,
                    Content = "<html><body><h4>Request not found</h4><p>There was no evaluation request associated with this verification code or it was already validated.</p></body></html>"
                };
            }

            tlr.Status = TrialRequestStatus.AwaitingApproval;
            tlr.EmailValidated = true;
            var res = await biz.PutAsync(tlr);
            if (res == null)
            {
                var msg = ($"Unexpected error processing a trial license request after email validation:{biz.GetErrorsAsString}");
                log.LogError(msg);
                await NotifyEventHelper.AddOpsProblemEvent(msg);
                return new ContentResult
                {
                    ContentType = "text/html",
                    StatusCode = 503,
                    Content = "<html><body><h4>Error processing request</h4><p>There was an internal error processing your request. Please try again or contact Support.</p></body></html>"
                };
            }


            return new ContentResult
            {
                ContentType = "text/html",
                StatusCode = 200,
                Content = "<html><body><h4>Email validated!</h4><p>Your request will be reviewed and processed by our staff <strong>during business hours</strong>. You will receive an email with instructions for starting your AyaNova evaluation.</p></body></html>"
            };
        }

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


    }//eoc
}//eons