using Knoks.Api.Entities;
using Knoks.Api.Filters;
using Knoks.Core.Entities.Args;
using Knoks.Core.Entities.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Knoks.Api.Controllers.Base
{
    [TypeFilter(typeof(ApiIdentifierActionFilter))]
    [TypeFilter(typeof(UserActionFilter))]
    [TypeFilter(typeof(OperatorActionFilter))]
    [TypeFilter(typeof(AutoInitFieldActionFilter))]
    [TypeFilter(typeof(LoggingActionFilter))]
    public abstract class ApiBaseController : Controller
    {
        public ApiConsumer ContextApiConsumer { get; set; }
        public long? ContextUserId { get; set; }
        public int? ContextOperatorId { get; set; }

        protected static ApiArray<T> ApiArray<T>(IEnumerable<T> items)
        {
            return new ApiArray<T>(items);
        }

        protected static ApiObject<T> ApiObject<T>(T obj)
        {
            return new ApiObject<T>(obj);
        }

        #region Check implementation 

        public class CheckPostArgs : IApiArgs
        {
            [JsonIgnore, AutoInitField]
            public string HttpRequestInfo { get; set; }

            [JsonIgnore, AutoInitField]
            public int ApiConsumerId { get; set; }
            [JsonIgnore, AutoInitField]
            public long UserId { get; set; }
            [JsonIgnore, AutoInitField]
            public int OperatorId { get; set; }
            public string Tag { get; set; }
        }

        public class CheckResult : IApiResult
        {
            public ApiConsumer ApiConsumer { get; set; }
            public long? UserId { get; set; }
            public int? OperatorId { get; set; }
            public string Tag { get; set; }
            public object Args { get; set; }
            public DateTime Timestamp { get; set; } = DateTime.UtcNow;
        }

        private async Task<CheckResult> GetResult(string tag, CheckPostArgs args = null)
        {
            return await Task.Run(() => new CheckResult
            {
                ApiConsumer = ContextApiConsumer,
                UserId = ContextUserId,
                OperatorId = ContextOperatorId,
                Tag = tag,
                Args = args == null ? null : new { args.ApiConsumerId, args.UserId, args.OperatorId, args.HttpRequestInfo },
                Timestamp = DateTime.UtcNow,
            });
        }

        [HttpGet("Check/{tag?}")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<CheckResult> Check([FromRoute]string tag)
        {
            return await GetResult(tag);
        }

        [HttpPost("Check")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<CheckResult> Check([FromBody]CheckPostArgs args)
        {
            return await GetResult(args.Tag, args);
        }

        [AllowAnonymous]
        [HttpGet("Policy")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<ApiObject<bool>> Policy()
        {
            return await Task.Run(() => ApiObject(true));
        }

        #endregion
    }
}
