    using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using Models;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Newtonsoft.Json;
using System.Security.Claims;
using System.Linq;
using System.Collections.Generic;
using System;
using SERVER;
using Microsoft.AspNetCore.Http;
using Quartz;
using System.Threading.Tasks;
using WebUI.LIB;
using COMMON;
using SERVER.LIB;

namespace WebUI.Controllers
{
    /// <summary>
    /// 基础控制器 判定权限
    /// </summary>
    public class BaseController : Controller
    {

        /// <summary>
        /// 用户 权限酒店原始数据 有分组
        /// </summary>
        public IList<HotelDataItem> Hotels = new List<HotelDataItem>();
        /// <summary>
        /// 用户 当前选择的酒店   这里的id 等于库里面 的  oLDid
        /// </summary>
        public HotelsItem SelHotel = new HotelsItem { };

        /// <summary>
        /// 用户 权限酒店
        /// </summary>
        public List<HotelsItem> Hoteldata = new List<HotelsItem>();

        /// <summary>
        /// 
        /// </summary>
        public Datainfo data { get; set; } = null;

        /// <summary>
        /// TOken 是用户名
        /// </summary>
        public string TOken { get; set; } = string.Empty;
        public string TOken_rom { get; set; } = string.Empty;
        public string Cookie { get; set; } = string.Empty;
        //复写父类的该方法。执行控制器中的方法之前先执行该方法。从而实现过滤的功能。
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);  //调用父类的该方法。
            Cookie = Request.Cookies["CurrentUser"];
            if (Cookie != null)
            {
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConst.Instance.SecurityKey));
                //校验token
                var validateParameter = new TokenValidationParameters()
                {
                    ValidateLifetime = true,
                    ValidateAudience = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = JwtConst.Instance.Domain,
                    ValidAudience = JwtConst.Instance.Domain,
                    IssuerSigningKey = key
                };
                //不校验，直接解析token
                //jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(token1);
                try
                {
                    //校验并解析token
                    var claimsPrincipal = new JwtSecurityTokenHandler().ValidateToken(Request.Cookies["CurrentUser"], validateParameter, out SecurityToken validatedToken);//validatedToken:解密后的对象
                    //var jwtPayload = ((JwtSecurityToken)validatedToken).Payload.SerializeToJson(); //获取payload中的数据 
                    TOken = claimsPrincipal.Identities.First().Name;
                    int[] rom = XC_Redis.Redis.GetKey<int[]>(TOken + Cookie.Substring(Cookie.Length - 8) + "_rom");
                    TOken_rom = TOken;
                    if (rom == null)
                    {
                        rom = XC_Redis.Redis.GetKey<int[]>(TOken + Cookie.Substring(Cookie.Length - 8) + "_rom_old");
                    };
                    if (rom == null)
                    {
                        throw new Exception();
                    };
                    foreach (var item in rom)
                    {
                        TOken_rom += Cookie[item];
                    }
                    data = XC_Redis.Redis.GetKey<Datainfo>(TOken);
                    if (data == null)
                    {
                        throw new Exception();
                    }
                    SelHotel = XC_Redis.Redis.GET(TOken_rom + "_sel", () =>
                    {
                        if (data.HotelData == null || data.HotelData.Count <= 0)
                        {
                            return null;
                        }
                        // 账号其他地方 登录  更新权限信息
                        // 同一账号 权限信息 共享  不会因为先登录而多用有某些权限
                        XC_Redis.Redis.Remove(TOken + "_Hoteldata");
                        return data.HotelData.FirstOrDefault().Hotels.FirstOrDefault();
                    });
                    Hotels = data.HotelData;

                    Hoteldata = XC_Redis.Redis.GET(TOken + "_Hoteldata", () =>
                    {
                        foreach (var item in Hotels)
                        {
                            Hoteldata.AddRange(item.Hotels);
                        }
                        return Hoteldata;
                    });

                    ViewBag.SelHotel = SelHotel;

                    ViewBag.Uname = TOken;

                    ViewBag.HeadImg = data.Userinfo.HeadImg;

                    string keys = data.Userinfo.Uid;


                }
                catch (SecurityTokenExpiredException ex)
                {
                    LogHelp.Error(ex.ToString());
                    //表示过期
                    filterContext.Result = Redirect("/Login/index?REURL=" + HttpContext.Request.GetDisplayUrl());
                }
                catch (SecurityTokenException ex)
                {
                    LogHelp.Error(ex.ToString());
                    //表示token错误
                    filterContext.Result = Redirect("/Login/index?REURL=" + HttpContext.Request.GetDisplayUrl());
                }
                catch (Exception ex)
                {
                    LogHelp.Error(ex.ToString());
                    filterContext.Result = Redirect("/Login/index?REURL=" + HttpContext.Request.GetDisplayUrl());
                }
            }
            else
            {
                //这种跳转方式直接返回一个ActionResult，不会继续向下执行，而是直接跳转。速度快。
                filterContext.Result = Redirect("/Login/index?REURL=" + HttpContext.Request.GetDisplayUrl());
            }
        }

        public static void SXTOKEN(BaseController baseController, HttpContext httpContext)
        {

            var keys = baseController.TOken;

            var claims = new[]
                    {
                        new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
                        new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddMinutes(20)).ToUnixTimeSeconds()}"),
                        new Claim(ClaimTypes.Name,keys)
                    };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConst.Instance.SecurityKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: JwtConst.Instance.Domain,
                audience: JwtConst.Instance.Domain,
                claims: claims,
                expires: DateTime.Now.AddMinutes(20),
                signingCredentials: creds);
            var RES = new ReturnData<string> { IsSuccess = true };
            string toke = new JwtSecurityTokenHandler().WriteToken(token);

            httpContext.Response.Cookies.Append("CurrentUser", toke);
         
            int[] rom = {
                        new Random(int.Parse(UtilsSharp.RandomHelper.Number(4))).Next(0, toke.Length),
                        new Random(int.Parse(UtilsSharp.RandomHelper.Number(4))).Next(0, toke.Length),
                        new Random(int.Parse(UtilsSharp.RandomHelper.Number(4))).Next(0, toke.Length),
                        new Random(int.Parse(UtilsSharp.RandomHelper.Number(4))).Next(0, toke.Length),
                    };

            XC_Redis.Redis.SetKey(keys + baseController.Cookie.Substring(baseController.Cookie.Length - 8) + "_rom_old", 
            
            XC_Redis.Redis.GetKey<int[]>(keys + baseController.Cookie.Substring(baseController.Cookie.Length - 8) + "_rom"), 10);

            XC_Redis.Redis.Remove(keys + baseController.Cookie.Substring(baseController.Cookie.Length - 8) + "_rom");

            XC_Redis.Redis.SetKey(keys + toke.Substring(toke.Length - 8) + "_rom", rom, 20);

            foreach (var item in rom)
            {
                keys += toke[item];
            }
            XC_Redis.Redis.SetKey(baseController.TOken, baseController.data, 20);
            XC_Redis.Redis.SetKey(keys + "_sel", baseController.SelHotel,20);
            XC_Redis.Redis.SetKey(baseController.TOken_rom + "_sel", baseController.SelHotel,10);
        }
    }
}
