using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;//required for authorize attribute
using System.Security.Claims;
using rockfishCore.Models;
using rockfishCore.Util;
using System.Linq;
using System;

//case 3233
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

//requried to inject configuration in constructor
using Microsoft.Extensions.Configuration;

//This is an 80 character line of text:
//##############################################################################
namespace rockfishCore.Controllers
{
    //Authentication controller
    [Produces("application/json")]
    [Route("api/License")]
    [Authorize]
    public class LicenseController : Controller
    {
        private readonly rockfishContext _context;
        private readonly IConfiguration _configuration;
        public LicenseController(rockfishContext context, IConfiguration configuration)//these two are injected, see startup.cs
        {
            _context = context;//Keeping db context here for future where I will be inserting the keys into the db upon generation
            _configuration = configuration;
        }


        ///////////////////////////////////////////////////////////////////////
        //KEYGEN ROUTES

        //Given key options return the message ready to send to the user 
        //Note this returns a key as plain text content result
        //called by rockfish client app.license.js (who calls app.api.createLicense)
        [HttpPost("generate")]
        public ContentResult Generate([FromBody] dtoKeyOptions ko)
        {
            var templates = _context.LicenseTemplates.ToList()[0];
            ko.authorizedUserKeyGeneratorStamp = GetRFAuthorizedUserStamp();
            string sKey = KeyFactory.GetKeyReply(ko, templates, _context);
            return Content(sKey);
        }



        //Fetch key request emails
        [HttpGet("requests")]
        public JsonResult GetRequests()
        {
            return Json(TrialKeyRequestHandler.Requests());
        }

        //Fetch generated responses
        //Generate a key from a license key request email
        //called by rockfish client app.licenseRequestEdit.js (who calls app.api.generateFromRequest)
        [HttpGet("generateFromRequest/{uid}")]
        public JsonResult GenerateFromRequest([FromRoute] uint uid)
        {
            var templates = _context.LicenseTemplates.ToList()[0];
            return Json(TrialKeyRequestHandler.GenerateFromRequest(uid, templates, GetRFAuthorizedUserStamp(), _context));
        }

        // SEND REQUESTED KEY ROUTE    
        //app.post('/api/license/email_response', function (req, res) {
        [HttpPost("email_response")]
        public JsonResult EmailResponse([FromBody] dtoKeyRequestResponse k)
        {
            return Json(TrialKeyRequestHandler.SendTrialRequestResponse(k));
        }





        ///////////////////////////////////////////////////////////
        // STORED LICENSE KEY CRUD ROUTES
        //

        //case 3233 Get api/license/list a list of generated licenses
        [HttpGet("list")]
        public IEnumerable<dtoLicenseListItem> GetList()
        {
            var res = from c in _context.License.OrderByDescending(c => c.DtCreated)
                      select new dtoLicenseListItem
                      {
                          id = c.Id,
                          created = c.DtCreated,
                          regto = c.RegTo,
                          fetched = c.Fetched,
                          trial = (c.CustomerId==0)
                      };
            return res.ToList();
        }

        //case 3233 GET: api/License/5
        [HttpGet("{id}")]
        public async Task<IActionResult> GetLicense([FromRoute] long id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var l = await _context.License.SingleOrDefaultAsync(m => m.Id == id);

            if (l == null)
            {
                return NotFound();
            }

            string customerName = "<TRIAL>";

            if (l.CustomerId != 0)
            {
                if (_context.Customer.Any(e => e.Id == l.CustomerId))
                {

                    var cust = await _context.Customer
                 .Select(r => new { r.Id, r.Name })
                                .Where(r => r.Id == l.CustomerId)
                                .FirstAsync();
                    customerName=cust.Name;
                }
                else
                {
                    customerName = "< Customer " + l.CustomerId.ToString() + " not found (deleted?) >";
                }
            }

            var ret = new
            {
                regTo = l.RegTo,
                customerName = customerName,
                dtcreated = l.DtCreated,
                email = l.Email,
                code = l.Code,
                fetched = l.Fetched,
                dtfetched = l.DtFetched,
                fetchFrom = l.FetchFrom,
                key = l.Key
            };

            return Ok(ret);
        }

        // DELETE: api/License/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteLicense([FromRoute] long id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var rec = await _context.License.SingleOrDefaultAsync(m => m.Id == id);
            if (rec == null)
            {
                return NotFound();
            }

            _context.License.Remove(rec);
            await _context.SaveChangesAsync();

            return Ok(rec);
        }


        // PUT: api/license/5/true
        //Update a license and set it's fetched property only
        //used by client to make a license fetchable or not ad-hoc
        [HttpPut("fetched/{id}/{isFetched}")]
        public async Task<IActionResult> PutLicenseFetched([FromRoute] long id, [FromRoute] bool isFetched)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var rec = await _context.License.SingleOrDefaultAsync(m => m.Id == id);
            if (rec == null)
            {
                return NotFound();
            }
            rec.Fetched = isFetched;

            _context.Entry(rec).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!LicenseExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }


            return NoContent();
        }



        private bool LicenseExists(long id)
        {
            return _context.License.Any(e => e.Id == id);
        }

        //===================== UTILITY =============
        private string GetRFAuthorizedUserStamp()
        {
            foreach (Claim c in User.Claims)
            {
                if (c.Type == "id")
                {
                    return "RFID" + c.Value;
                }
            }
            return "RFID unknown";
        }

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

    }//eoc
}//eons