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.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

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


namespace AyaNova.Api.Controllers
{

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

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



        /// <summary>
        /// Create search parameters
        /// MaxResults defaults to 500 
        /// MaxResults = 0 returns all results 
        /// </summary>
        /// <param name="searchParams"></param>
        /// <returns>SearchResult list</returns>
        [HttpPost]
        public async Task<IActionResult> PostSearch([FromBody] Search.SearchRequestParameters searchParams)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

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

            //Do the search
            var SearchResults = await Search.DoSearchAsync(ct, UserTranslationIdFromContext.Id(HttpContext.Items), UserRolesFromContext.Roles(HttpContext.Items), searchParams);

            return Ok(ApiOkResponse.Response(SearchResults));
        }

        /// <summary>
        /// Get search result summary
        /// </summary>
        /// <param name="ayaType"></param>
        /// <param name="id"></param>
        /// <param name="phrase"></param>
        ///  <param name="max"></param>
        /// <returns>A search result excerpt of object</returns>
        [HttpGet("info/{ayaType}/{id}")]
        public async Task<IActionResult> GetInfo([FromRoute] AyaType ayaType, [FromRoute] long id, [FromQuery] string phrase, [FromQuery] int max = 80)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

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

            if (!ModelState.IsValid)
                return BadRequest(new ApiErrorResponse(ModelState));
            if (id == 0)            
                return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, "id", "id can't be zero"));
            

            var res = await Search.GetInfoAsync(UserTranslationIdFromContext.Id(HttpContext.Items),
            UserRolesFromContext.Roles(HttpContext.Items), UserIdFromContext.Id(HttpContext.Items), phrase, max, ayaType, id, ct);

            return Ok(ApiOkResponse.Response(res));
        }



        /// <summary>
        /// Get the top level ancestor of provided type and id
        /// (e.g. find the WorkOrder principle for a WorkOrderItemPart object descendent)
        /// </summary>
        /// <param name="ayaType"></param>
        /// <param name="id"></param>        
        /// <returns>A type and id of ancestor</returns>
        [HttpGet("ancestor/{ayaType}/{id}")]
        public async Task<IActionResult> GetAncestor([FromRoute] AyaType ayaType, [FromRoute] long id)
        {
            if (serverState.IsClosed)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

            //since this is for opening an entire object it's appropriate to check if they have read full role first
            if (!Authorized.HasReadFullRole(HttpContext.Items, ayaType))
                return StatusCode(403, new ApiNotAuthorizedResponse());

            if (!ModelState.IsValid)
                return BadRequest(new ApiErrorResponse(ModelState));
            if (id == 0)
               return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, "id can't be zero"));
               
            switch (ayaType)
            {
                case AyaType.WorkOrderItem:
                case AyaType.WorkOrderItemExpense:
                case AyaType.WorkOrderItemLabor:
                case AyaType.WorkOrderItemLoan:
                case AyaType.WorkOrderItemPart:
                case AyaType.WorkOrderItemPartRequest:
                case AyaType.WorkOrderItemScheduledUser:
                case AyaType.WorkOrderItemTask:
                case AyaType.WorkOrderItemTravel:
                    AyaTypeId TypeId = await WorkOrderBiz.GetAncestor(ayaType, id, ct);
                    return Ok(ApiOkResponse.Response(new { AyaType = TypeId.ObjectTypeAsInt, Id = TypeId.ObjectId }));
                default:
                    return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, "Only types with ancestors are valid"));

            }

        }



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


    }//eoc
}//eons