using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
using AyaNova.Util;


namespace AyaNova.Api.Controllers
{

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


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


        /// <summary>
        /// Get name value Translated display value list of AyaNova enumerated types for list specified
        /// </summary>
        /// <param name="enumkey">The key name of the enumerated type</param>
        /// <returns>List</returns>
        [HttpGet("list/{enumkey}")]
        public ActionResult GetList([FromRoute]string enumkey)
        {
            if (serverState.IsClosed)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

            long TranslationId = UserTranslationIdFromContext.Id(HttpContext.Items);
            List<string> TranslationKeysToFetch = new List<string>();

            List<NameIdItem> ReturnList = new List<NameIdItem>();

            var keyNameInLowerCase = enumkey.ToLowerInvariant();


            if (keyNameInLowerCase == StringUtil.TrimTypeName(typeof(UiFieldDataType).ToString()).ToLowerInvariant())
            {
                //Iterate the enum and get the values
                Type t = typeof(UiFieldDataType);
                Enum.GetName(t, UiFieldDataType.NoType);
                foreach (var dt in Enum.GetValues(t))
                {
                    ReturnList.Add(new NameIdItem() { Name = Enum.GetName(t, dt), Id = (int)dt });
                }

            }
            else if (keyNameInLowerCase == "core")
            {
                //core biz objects for UI facing purposes such as search form limit to object type etc
                var values = Enum.GetValues(typeof(AyaType));
                foreach (AyaType t in values)
                {
                    if (t.HasAttribute(typeof(CoreBizObjectAttribute)))
                    {
                        TranslationKeysToFetch.Add(t.ToString());
                    }
                }
                var LT = TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, TranslationId).Result;

                foreach (AyaType t in values)
                {
                    if (t.HasAttribute(typeof(CoreBizObjectAttribute)))
                    {
                        var tName = t.ToString();
                        string name = string.Empty;
                        if (LT.ContainsKey(tName))
                        {
                            name = LT[tName];
                        }
                        else
                        {
                            name = tName;
                        }
                        ReturnList.Add(new NameIdItem() { Name = name, Id = (long)t });
                    }
                }
            }
            else if (keyNameInLowerCase == StringUtil.TrimTypeName(typeof(AyaType).ToString()).ToLowerInvariant())
            {
                //this is intended primarily for developers, not for UI facing so no need to localize or pretty it up
                //bullshit, it's just extra work not translated and developers only need the number, not the enumeration name which is for here only

                var values = Enum.GetValues(typeof(AyaType));

                foreach (AyaType t in values)
                    TranslationKeysToFetch.Add(t.ToString());
                var LT = TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, TranslationId).Result;

                foreach (AyaType t in values)
                {
                    string tName = t.ToString();
                    string name = string.Empty;
                    if (LT.ContainsKey(tName))
                    {
                        name = LT[tName];
                    }
                    else
                    {
                        name = tName;
                    }
                    ReturnList.Add(new NameIdItem() { Name = name, Id = (long)t });
                }
            }
            else if (keyNameInLowerCase == StringUtil.TrimTypeName(typeof(UserType).ToString()).ToLowerInvariant())
            {
                TranslationKeysToFetch.Add("UserTypeAdministrator");
                TranslationKeysToFetch.Add("UserTypeService");
                TranslationKeysToFetch.Add("UserTypeNotService");
                TranslationKeysToFetch.Add("UserTypeCustomer");
                TranslationKeysToFetch.Add("UserTypeHeadOffice");
                TranslationKeysToFetch.Add("UserTypeServiceContractor");
                TranslationKeysToFetch.Add("UserTypeUtility");
                var LT = TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, TranslationId).Result;

                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeAdministrator"], Id = (long)UserType.Administrator });
                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeService"], Id = (long)UserType.Service });
                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeNotService"], Id = (long)UserType.NotService });
                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeCustomer"], Id = (long)UserType.Customer });
                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeHeadOffice"], Id = (long)UserType.HeadOffice });
                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeUtility"], Id = (long)UserType.Utility });
                ReturnList.Add(new NameIdItem() { Name = LT["UserTypeServiceContractor"], Id = (long)UserType.ServiceContractor });
            }
            else if (keyNameInLowerCase == StringUtil.TrimTypeName(typeof(AuthorizationRoles).ToString()).ToLowerInvariant())
            {

                TranslationKeysToFetch.Add("AuthorizationRoleNoRole");
                TranslationKeysToFetch.Add("AuthorizationRoleBizAdminLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleBizAdminFull");
                TranslationKeysToFetch.Add("AuthorizationRoleDispatchLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleDispatchFull");
                TranslationKeysToFetch.Add("AuthorizationRoleInventoryLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleInventoryFull");
                TranslationKeysToFetch.Add("AuthorizationRoleAccountingFull");
                TranslationKeysToFetch.Add("AuthorizationRoleTechLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleTechFull");
                TranslationKeysToFetch.Add("AuthorizationRoleSubContractorLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleSubContractorFull");
                TranslationKeysToFetch.Add("AuthorizationRoleCustomerLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleCustomerFull");
                TranslationKeysToFetch.Add("AuthorizationRoleOpsAdminLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleOpsAdminFull");
                TranslationKeysToFetch.Add("AuthorizationRoleSalesLimited");
                TranslationKeysToFetch.Add("AuthorizationRoleSalesFull");
                TranslationKeysToFetch.Add("AuthorizationRoleAll");
                var LT = TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, TranslationId).Result;

                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleNoRole"], Id = (long)AuthorizationRoles.NoRole });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleBizAdminLimited"], Id = (long)AuthorizationRoles.BizAdminLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleBizAdminFull"], Id = (long)AuthorizationRoles.BizAdminFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleDispatchLimited"], Id = (long)AuthorizationRoles.DispatchLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleDispatchFull"], Id = (long)AuthorizationRoles.DispatchFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleInventoryLimited"], Id = (long)AuthorizationRoles.InventoryLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleInventoryFull"], Id = (long)AuthorizationRoles.InventoryFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleAccountingFull"], Id = (long)AuthorizationRoles.AccountingFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleTechLimited"], Id = (long)AuthorizationRoles.TechLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleTechFull"], Id = (long)AuthorizationRoles.TechFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSubContractorLimited"], Id = (long)AuthorizationRoles.SubContractorLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSubContractorFull"], Id = (long)AuthorizationRoles.SubContractorFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleCustomerLimited"], Id = (long)AuthorizationRoles.CustomerLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleCustomerFull"], Id = (long)AuthorizationRoles.CustomerFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleOpsAdminLimited"], Id = (long)AuthorizationRoles.OpsAdminLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleOpsAdminFull"], Id = (long)AuthorizationRoles.OpsAdminFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSalesLimited"], Id = (long)AuthorizationRoles.SalesLimited });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleSalesFull"], Id = (long)AuthorizationRoles.SalesFull });
                ReturnList.Add(new NameIdItem() { Name = LT["AuthorizationRoleAll"], Id = (long)AuthorizationRoles.All });

            }
            else
            {
                ReturnList.Add(new NameIdItem() { Name = $"Unknown enum type list key value {enumkey}", Id = (long)UserType.Administrator });
            }



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




        /// <summary>
        /// Get all possible enumerated values list key names
        /// </summary>     
        /// <returns>List of AyaNova enumerated type list key names that can be fetched from the GetList Route</returns>
        [HttpGet("listkeys")]
        public ActionResult GetTypesList()
        {
            if (!serverState.IsOpen)
                return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

            List<KeyValuePair<string, string>> ret = new List<KeyValuePair<string, string>>();
            ret.Add(new KeyValuePair<string, string>(StringUtil.TrimTypeName(typeof(UserType).ToString()), "AyaNova user account types"));
            ret.Add(new KeyValuePair<string, string>(StringUtil.TrimTypeName(typeof(AuthorizationRoles).ToString()), "AyaNova user account role types"));
            ret.Add(new KeyValuePair<string, string>(StringUtil.TrimTypeName(typeof(AyaType).ToString()), "All AyaNova object types"));
            ret.Add(new KeyValuePair<string, string>("Core", "All Core AyaNova business object types"));
            ret.Add(new KeyValuePair<string, string>(StringUtil.TrimTypeName(typeof(UiFieldDataType).ToString()), "Types of data used in AyaNova for display and formatting UI purposes"));

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




    }//eoc
}//ens