using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;


namespace AyaNova.Api.Controllers
{

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


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


        /// <summary>
        /// Get full DataFilter object
        /// 
        /// Required roles:
        /// Any (for public filter), owned only for private filter
        /// </summary>
        /// <param name="id"></param>
        /// <returns>A single DataFilter</returns>
        [HttpGet("{id}")]
        public async Task<IActionResult> GetDataFilter([FromRoute] long id)
        {
            if (serverState.IsClosed)
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));

            //Instantiate the business object handler
            DataFilterBiz biz = DataFilterBiz.GetBiz(ct, HttpContext);

            if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType))
                return StatusCode(403, new ApiNotAuthorizedResponse());

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

            var o = await biz.GetAsync(id);
            if (o == null)
                return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));

            return Ok(ApiOkResponse.Response(o, !Authorized.HasModifyRole(HttpContext.Items, biz.BizType)));
        }



        /// <summary>
        /// Get DataFilter pick list
        /// 
        /// Required roles: Any
        /// 
        /// </summary>
        /// <returns>List of public or owned data filters for listKey provided</returns>    
        [HttpGet("PickList", Name = nameof(DataFilterPickList))]
        public async Task<IActionResult> DataFilterPickList([FromQuery] string ListKey)
        {
            if (serverState.IsClosed)
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));

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

            //Instantiate the business object handler
            DataFilterBiz biz = DataFilterBiz.GetBiz(ct, HttpContext);

            var l = await biz.GetPickListAsync(ListKey);
            return Ok(ApiOkResponse.Response(l, true));

        }


        /// <summary>
        /// Put (update) DataFilter
        /// 
        /// Required roles:
        /// Any (public filter) or owned only (private filter)
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="inObj"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task<IActionResult> PutDataFilter([FromRoute] long id, [FromBody] DataFilter inObj)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));

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

            //Instantiate the business object handler       
            DataFilterBiz biz = DataFilterBiz.GetBiz(ct, HttpContext);

            var o = await biz.GetNoLogAsync(id);
            if (o == null)
                return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));

            if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType))
                return StatusCode(403, new ApiNotAuthorizedResponse());

            try
            {
                if (!biz.Put(o, inObj))
                    return BadRequest(new ApiErrorResponse(biz.Errors));
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!await biz.ExistsAsync(id))
                    return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
                else
                    return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT));
            }
            return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true));
        }


        /// <summary>
        /// Post DataFilter
        /// 
        /// Required roles: 
        /// BizAdminFull, InventoryFull, TechFull
        /// </summary>
        /// <param name="inObj"></param>
        /// <param name="apiVersion">Automatically filled from route path, no need to specify in body</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> PostDataFilter([FromBody] DataFilter inObj, ApiVersion apiVersion)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));

            //Instantiate the business object handler
            DataFilterBiz biz = DataFilterBiz.GetBiz(ct, HttpContext);

            //If a user has change roles, or editOwnRoles then they can create, true is passed for isOwner since they are creating so by definition the owner
            if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
                return StatusCode(403, new ApiNotAuthorizedResponse());

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

            //Create and validate
            DataFilter o = await biz.CreateAsync(inObj);
            if (o == null)
                return BadRequest(new ApiErrorResponse(biz.Errors));
            else
                return CreatedAtAction(nameof(DataFilterController.GetDataFilter), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));

        }



        /// <summary>
        /// Delete DataFilter
        /// 
        /// Required roles:
        /// Any if public otherwise creator only
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns>Ok</returns>
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteDataFilter([FromRoute] long id)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason));

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

            //Instantiate the business object handler
            DataFilterBiz biz = DataFilterBiz.GetBiz(ct, HttpContext);

            var o = await biz.GetNoLogAsync(id);
            if (o == null)
                return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));

            if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType))
                return StatusCode(403, new ApiNotAuthorizedResponse());

            if (!biz.Delete(o))
                return BadRequest(new ApiErrorResponse(biz.Errors));

            return NoContent();
        }

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


    }//eoc
}//eons