using C4IT.F4SDM;
using C4IT.FASD.Base;
using C4IT.Logging;
using Matrix42.Common;
using Matrix42.Contracts.ServiceManagement.ServiceContracts;
using Matrix42.Pandora.Contracts;
using Matrix42.Services.Description.Contracts;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.OData;
using System.Web.OData.Query;
using update4u.SPS.Utility.GlobalConfiguration;
using static C4IT.FASD.Base.cF4SDTicket;
using static C4IT.Logging.cLogManager;

namespace C4IT.F4SD
{
    [RoutePrefix("api/C4ITF4SDWebApi")]
    public partial class F4SDM42WebApiController : ApiController
    {
        public static bool IsInitialized { get; private set; } = false;
        public static F4SDM42WebApiController defaultInstance;
        //private readonly IIncidentService _incidentService;
        internal readonly GlobalConfigurationProvider _globalConfigurationProvider;
        public readonly IJournalService _journalService;
        //public readonly IObjectService _objectService;
        //public readonly IFragmentService _fragmentService;
        internal readonly IEntityDataService _entityDataService;
        internal readonly IPandoraUserProfile _userProfile;


        private readonly F4SDHelperService _f4stHelperService;
        public string BaseUrl => $"{Request.RequestUri.Scheme}://{Request.RequestUri.Host}";
        public string EndpointBaseUrl => $"{BaseUrl}/m42Services/api/c4itf4sdwebapi";
        public F4SDM42WebApiController(
            //IObjectService objectService,
            //IIncidentService incidentService,
            IJournalService journalService
            //IFragmentService fragmentService,
            , IEntityDataService entityDataService
            , IPandoraUserProfile userProfile
            )
        {
            defaultInstance = this;
            //_objectService = objectService;
            //_fragmentService = fragmentService;
            //_incidentService = Guard.NullArgument(incidentService, "incidentService");

            _entityDataService = entityDataService;
            _journalService = journalService;
            _globalConfigurationProvider = GlobalConfigurationProvider.Instance;
            _f4stHelperService = new F4SDHelperService();
            _userProfile = userProfile;
        }

        private static object initLock = new object();
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            try
            {
                //System.Diagnostics.Debugger.Launch();
                lock (initLock)
                {
                    if (IsInitialized || F4SDM42LogsWebApiController.IsInitialized)
                        return;
                    var Ass = Assembly.GetExecutingAssembly();
                    var LM = cLogManagerFile.CreateInstance(LocalMachine: true, A: Ass);
                    var CM = MethodBase.GetCurrentMethod();
                    LogMethodBegin(CM);
                    cLogManager.DefaultLogger.LogAssemblyInfo(Ass);
                    IsInitialized = true;
                    LogMethodEnd(CM);
                }
            }
            catch { };
        }

        [Route("getDirectLinkCreateTicket"), HttpGet]
        public async Task<F4SDHelperService.DirectLink> getDirectLinkCreateTicket(string sid = "", string assetname = "")
        {
            await Task.Delay(0);
            return await _f4stHelperService.getDirectLinkCreateTicket(sid, assetname);
        }
        [Route("getDirectLinkF4SD"), HttpGet]
        public async Task<string> getDirectLinkF4SD(Guid EOID, string Type)
        {
            return await _f4stHelperService.getDirectLinkF4SD(EOID, Type);
        }

        [Route("getTicketList"), HttpGet]
        public async Task<List<cF4SDTicketSummary>> getTicketList(
            string sid,
            int hours,
            int queueoption = 0,
            string queues = ""
        )
        {
            var decodedPairs = ParseQueues(queues);

            // Nun weiterreichen an Service
            return await _f4stHelperService.getTicketListByUser(
                sid,
                hours,
                queueoption,
                decodedPairs
            );
        }


        [Route("getTicketDetails"), HttpGet]
        public async Task<cF4SDTicket> getTicketDetails(Guid objectId)
        {
            var tickets = await _f4stHelperService.getTicketDetails(new List<Guid>() { objectId });
            if (tickets.Count > 0)
                return tickets[0];
            else
                return null;
        }

        [Route("getTicketHistory"), HttpGet]
        public async Task<List<cTicketJournalItem>> getTicketHistory(Guid objectId)
        {
            return await _f4stHelperService.GetJournalEntries(objectId);
        }

        [Route("getTicketOverviewCounts"), HttpGet]
        public async Task<F4SDHelperService.TicketOverviewCountsResult> getTicketOverviewCounts(
            string sid,
            string scope = "personal",
            string keys = "",
            int queueoption = 0,
            string queues = ""
        )
        {
            var parsedKeys = (keys ?? string.Empty)
                .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(key => key.Trim())
                .Where(key => !string.IsNullOrWhiteSpace(key))
                .ToList();

            var decodedQueues = ParseQueues(queues);
            return await _f4stHelperService.getTicketOverviewCounts(sid, scope, parsedKeys, queueoption, decodedQueues);
        }

        [Route("getTicketOverviewCountsByRoles"), HttpPost]
        public async Task<F4SDHelperService.TicketOverviewCountsByRoleResult> getTicketOverviewCountsByRoles([FromBody] TicketOverviewCountsByRolesRequest request)
        {
            var parsedKeys = (request?.Keys ?? new List<string>())
                .Where(key => !string.IsNullOrWhiteSpace(key))
                .Select(key => key.Trim())
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .ToList();

            var roleGuids = (request?.RoleGuids ?? new List<Guid>())
                .Where(roleId => roleId != Guid.Empty)
                .Distinct()
                .ToList();

            var decodedQueues = ParseQueues(request?.Queues ?? string.Empty);
            return await _f4stHelperService.getTicketOverviewCountsByRoles(
                request?.Sid,
                roleGuids,
                parsedKeys,
                request?.QueueOption ?? 0,
                decodedQueues
            );
        }

        [Route("getTicketOverviewRelations"), HttpGet]
        public async Task<List<F4SDHelperService.TicketOverviewRelationDto>> getTicketOverviewRelations(
            string sid,
            string scope = "personal",
            string key = "",
            int count = 0,
            int queueoption = 0,
            string queues = ""
        )
        {
            var decodedQueues = ParseQueues(queues);
            return await _f4stHelperService.getTicketOverviewRelations(sid, scope, key, count, queueoption, decodedQueues);
        }
        /*
        [Route("updateActivitySolution/{objectId}"), HttpPost]
        public async Task<HttpResponseMessage> updateActivitySolution(Guid objectId, [FromBody] string SolutionHtml)
        {
            return new HttpResponseMessage
            {
                StatusCode = await _f4stHelperService.updateActivitySolution(objectId, SolutionHtml) ? HttpStatusCode.NoContent : HttpStatusCode.BadRequest,
            };
        }
        */
        [Route("getPickup/{name}"), HttpGet]
        //[CacheOutput(UseETAG = true)]
        public async Task<HttpResponseMessage> getPickup(string name, [FromUri] EntityEnumerationVisibilityMode mode = EntityEnumerationVisibilityMode.None, [FromUri] Int32 group = -1)
        {
            await Task.Delay(0);
            EntityEnumeration enumerationTemp = _entityDataService.GetEnumeration(name, mode);
            var vals = enumerationTemp.Values;

            if (group > -1)
            {
                vals = vals.Where(row => !row.Extentions.TryGetValue("StateGroup", out var stateGroup) || (ConvertHelper.ParseInt(stateGroup, 0) == group)).ToArray();
            }

            string[] columns = new string[] { "position" };
            foreach (var item in vals)
            {
                item.Extentions = item.Extentions.Where(x => columns.Contains(x.Key.ToLower())).ToDictionary(x => x.Key, x => x.Value);
            }

            EntityEnumeration enumeration = new EntityEnumeration
            {
                Name = enumerationTemp.Name,
                Values = vals.ToArray()
            };
            //CacheOutputAttribute.RegisterResponseEtag($"enum_{enumeration.Name}_{(int)mode}", $"{enumeration.Name}_{(int)mode}", cultureInvariant: false, userInvariant: true, val);
            return Request.CreateResponse(HttpStatusCode.OK, enumeration);
        }

        [Route("getMyRoleMemberships", Order = 2), HttpGet]
        public async Task<HttpResponseMessage> getMyRoleMemberships()
        {
            var User = _userProfile.GetInteractiveUserInfo();
            var filter = AsqlHelper.BuildInCondition("ID", new Guid[] { User.Id });
            return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
        }
        [HttpGet]
        [Route("getRoleMemberships", Order = 1)]
        public async Task<HttpResponseMessage> getRoleMemberships([FromUri] GetRoleMembershipsRequest req)
        {
            var filter = "";

            if (req.Id != null && req.Id.Value != Guid.Empty)
            {
                filter = AsqlHelper.BuildInCondition("ID", new Guid[] { req.Id.Value });
            }
            else if (!string.IsNullOrEmpty(req.Sid))
            {
                filter = AsqlHelper.BuildInCondition("Accounts.T(SPSAccountClassAD).Sid", new string[] { req.Sid });
            }
            else if (!string.IsNullOrEmpty(req.Upn))
            {
                filter = AsqlHelper.BuildInCondition("Accounts.T(SPSAccountClassAD).UserPrincipalName", new string[] { req.Upn });
            }

            if (!string.IsNullOrEmpty(filter))
            {
                return Request.CreateResponse(HttpStatusCode.OK, await _f4stHelperService.UserPermissionsInfo(filter));
            }
            else
            {
                return null;
            }
        }

        public class GetRoleMembershipsRequest
        {
            public Guid? Id { get; set; }
            public string Sid { get; set; }
            public string Upn { get; set; }
            public GetRoleMembershipsRequest() { }
        }

        public class TicketOverviewCountsByRolesRequest
        {
            public string Sid { get; set; }
            public List<Guid> RoleGuids { get; set; } = new List<Guid>();
            public List<string> Keys { get; set; } = new List<string>();
            public int? QueueOption { get; set; }
            public string Queues { get; set; }
        }

        private static List<cApiM42TicketQueueInfo> ParseQueues(string queues)
        {
            return (queues ?? string.Empty)
                .Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(part =>
                {
                    var segments = part.Split(':');
                    if (segments.Length != 2)
                        return null;

                    var name = HttpUtility.UrlDecode(segments[0]);
                    var idStr = HttpUtility.UrlDecode(segments[1]);

                    return Guid.TryParse(idStr, out var guid)
                        ? new cApiM42TicketQueueInfo { QueueName = name, QueueID = guid }
                        : null;
                })
                .Where(q => q != null)
                .ToList();
        }

        [Route("isAlive"), HttpGet]
        public HttpResponseMessage isAlive()
        {
            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }

        [Route("loglevel"), HttpGet]
        public async Task<string> setDebugMode(string debug = "0")
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                await Task.Delay(0);
                DefaultLogger.Manager.Level = debug == "1" || debug.Equals("true", StringComparison.OrdinalIgnoreCase) ? LogLevels.Debug : LogLevels.Info;
                return DefaultLogger.Manager.Level.ToString();
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        [Route("log"), HttpGet]
        public HttpResponseMessage getLog(string download = "0", int count = 50, string filter = "")
        {
            try
            {
                return _f4stHelperService.privGetLog(download, count, Request, filter);
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
        }
    }
    [RoutePrefix("api/C4ITF4SDWebApi/Logs")]
    public partial class F4SDM42LogsWebApiController : ApiController
    {
        private readonly F4SDHelperService _f4stHelperService;

        public static bool IsInitialized { get; private set; } = false;

        private static object initLock = new object();
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            try
            {
                lock (initLock)
                {
                    if (IsInitialized || F4SDM42WebApiController.IsInitialized)
                        return;
                    var Ass = Assembly.GetExecutingAssembly();
                    var LM = cLogManagerFile.CreateInstance(LocalMachine: true, A: Ass);
                    var CM = MethodBase.GetCurrentMethod();
                    LogMethodBegin(CM);
                    cLogManager.DefaultLogger.LogAssemblyInfo(Ass);
                    IsInitialized = true;
                    LogMethodEnd(CM);
                }
            }
            catch { };
        }



        public F4SDM42LogsWebApiController()
        {
            _f4stHelperService = new F4SDHelperService();
        }

        [Route(""), HttpGet]
        [EnableQuery]
        public IEnumerable<cM42LogEntry> getLog2(ODataQueryOptions<cM42LogEntry> queryOptions)
        {
            try
            {
                IQueryable<cM42LogEntry> queryable = _f4stHelperService.privGetLog2().AsQueryable();
                if (queryOptions.Filter != null)
                {
                    queryable = queryOptions.Filter.ApplyTo(queryable, new ODataQuerySettings()).Cast<cM42LogEntry>();
                }
                return queryable;
            }
            catch (Exception E)
            {
                LogException(E);
                return null;
            }
        }

        [Route("$count")]
        [HttpGet]
        public int Log2Count(ODataQueryOptions<cM42LogEntry> queryOptions)
        {
            IQueryable<cM42LogEntry> queryable = _f4stHelperService.privGetLog2().AsQueryable();
            if (queryOptions.Filter != null)
            {
                queryable = queryOptions.Filter.ApplyTo(queryable, new ODataQuerySettings()).Cast<cM42LogEntry>();
            }
            return queryable.Count();
        }

        [Route("{id}")]
        [OperationType(OperationType.GetObject)]
        public cM42LogEntry GetClass(int id)
        {
            return _f4stHelperService.privGetLog2(id);
        }
    }

    public class cGetPropertyBody
    {
        public string TableName { get; set; }
        public List<string> Columns { get; set; } = new List<string>();
        public cGetPropertyBody() { }

    }
}
