using System;
using System.Threading.Tasks;
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;


namespace AyaNova.Api.Controllers
{

    /// <summary>
    /// Log files controller
    /// </summary>
    [ApiController]
    [ApiVersion("8.0")]
    [Route("api/v{version:apiVersion}/event-log")]
    [Authorize]
    public class EventLogController : ControllerBase
    {
        private readonly AyContext ct;
        private readonly ILogger<LogFilesController> log;
        private readonly ApiServerState serverState;


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




        /// <summary>
        /// Get event log for object and range specified
        /// 
        /// Required Role: Read full object properties rights to object type specified
        /// 
        /// </summary>        
        /// <returns>Event log entry list for object</returns>
        [HttpGet("objectlog")]
        public async Task<IActionResult> GetObjectLog([FromQuery] EventLogOptions opt)
        {
            if (serverState.IsClosed)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

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

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

            var ret = await EventLogProcessor.GetLogForObjectAsync(opt, ct);
            return Ok(ApiOkResponse.Response(ret));
        }



        /// <summary>
        /// Get event log entries for a specified user and range
        /// 
        /// Required Role: Read rights to User object or User's own data
        /// 
        /// </summary>        
        /// <returns>Event log for user</returns>
        [HttpGet("userlog")]
        public async Task<IActionResult> GetUserLog([FromQuery] UserEventLogOptions opt)
        {
            if (serverState.IsClosed)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

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

            long UserId = UserIdFromContext.Id(HttpContext.Items);

            //If not authorized to read a user and also not the current user asking for their own log then NO LOG FOR YOU!
            if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.User) && opt.UserId != UserId)
            {
                return StatusCode(403, new ApiNotAuthorizedResponse());
            }

            var ret = await EventLogProcessor.GetLogForUserAsync(opt, ct);
            return Ok(ApiOkResponse.Response(ret));
        }


        /// <summary>
        /// V7 export replace log entry
        /// (internal use only)
        /// </summary>
        /// <param name="inObj"></param>
        /// <param name="apiVersion">From route path</param>
        /// <returns></returns>
        [ApiExplorerSettings(IgnoreApi = true)]
        [HttpPost("v7")]
        public async Task<IActionResult> PostV7Modify([FromBody] V7Event inObj, ApiVersion apiVersion)
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

           //NOTE: only bizadmin full and opsadminfull have this right so it's perfect for this task
            if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.License))           
                return StatusCode(403, new ApiNotAuthorizedResponse());

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

            await EventLogProcessor.V7_Modify_LogAsync(inObj, ct);
            return NoContent();
        }
        public sealed class V7Event
        {
            public AyaType AyaType { get; set; }
            public long AyId { get; set; }
            public long Creator { get; set; }
            public long Modifier { get; set; }
            public DateTime Created { get; set; }
            public DateTime Modified { get; set; }

        }

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


        public sealed class EventLogOptions
        {
            [FromQuery]
            public AyaType AyaType { get; set; }
            [FromQuery]
            public long AyId { get; set; }
            [FromQuery]
            public int? Offset { get; set; }
            [FromQuery]
            public int? Limit { get; set; }
        }

        public sealed class UserEventLogOptions
        {

            [FromQuery]
            public long UserId { get; set; }
            [FromQuery]
            public int? Offset { get; set; }
            [FromQuery]
            public int? Limit { get; set; }
        }

        public sealed class ObjectEventLog
        {
            public string Name { get; set; }
            public ObjectEventLogItem[] Events { get; set; }
        }

        public sealed class ObjectEventLogItem
        {
            //DateTime, UserId, Event, Textra           
            public DateTime Date { get; set; }
            public long UserId { get; set; }
            public string Name { get; set; }
            public AyaEvent Event { get; set; }
            public string Textra { get; set; }
        }

        public sealed class UserEventLog
        {
            public string Name { get; set; }
            public UserEventLogItem[] Events { get; set; }
        }

        public sealed class UserEventLogItem
        {
            //DateTime, ObjectType, ObjectId, Event, Textra       
            public DateTime Date { get; set; }
            public AyaType ObjectType { get; set; }
            public long ObjectId { get; set; }
            public string Name { get; set; }
            public AyaEvent Event { get; set; }
            public string Textra { get; set; }
        }


    }//eoc
}//eons