using DotNetCore.CAP;
using Furion;
using Furion.DistributedIDGenerator;
using Microsoft.AspNetCore.Mvc;
using Nirvana.Common;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.AdvancedAPIs.OAuth;
using Senparc.Weixin.MP.Helpers;
using System.Text;
using System.Web;
using YBDevice.Body.BodyFatHelper;
using YBDevice.Entity;

namespace YBDevice.NApi.Controllers
{
    /// <summary>
    /// 扫码流程处理
    /// </summary>
    public class QrController : WebBaseController
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IOrderService _orderService;
        private readonly IDeviceService _deviceService;
        private readonly INoticeService _noticeService;
        private readonly IMPService _mPService;
        private readonly ICapPublisher _capBus;

        public QrController(IHttpContextAccessor httpContextAccessor, IOrderService orderService,
            IDeviceService deviceService,
            INoticeService noticeService, IMPService mPService, ICapPublisher capPublisher)
        {
            _httpContextAccessor = httpContextAccessor;
            _orderService = orderService;
            _deviceService = deviceService;
            _noticeService = noticeService;
            _mPService = mPService;
            _capBus = capPublisher;
        }

        #region 固定贴纸处理

        /// <summary>
        /// 扫码主入口,针对固定的贴纸二维码,即可跳转到小程序又可关注公众号也可跳转链接
        /// </summary>
        /// <param name="sn">产品序列号</param>
        /// <returns></returns>
        public async Task<IActionResult> r(string sn)
        {
            //sn过滤空格
            sn = sn.ToStr();

            if (sn == "L228000103")
            {
                return Redirect($"https://ijt.pcxbc.com/qr/r/MA==?t=7");
            }

            //是否跳转到新平台
            if (await _orderService.IsNewPlatformAsync(sn))
            {
                return Redirect($"{App.Configuration["CustomSetting:NewPltUrl"]}/qr/r?sn={sn}");
            }
            //对参数进行base64编码
            var data = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{sn}"));
            var url = $"{Configs.GetString("APIURL")}/Qr/e?data={data}";
            //对url进行base64编码
            url = Convert.ToBase64String(Encoding.UTF8.GetBytes(url));
            //跳转授权页面
            var state = "xbpage";//用于识别请求可靠性
            var redirecturl = $"{Configs.GetString("APIURL")}/Auth/page?r={url}";
            var rurl = OAuthApi.GetAuthorizeUrl(appId, redirecturl, state, OAuthScope.snsapi_userinfo);
            return Redirect(rurl);
        }

        /// <summary>
        /// 固定贴纸处理流程
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> eAsync(string data, string info)
        {
            var ua = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
            //对data进行base64解密
            var facecode = Encoding.UTF8.GetString(Convert.FromBase64String(data));
            //对info进行base64解密，然后urldecode解码
            info = HttpUtility.UrlDecode(Encoding.UTF8.GetString(Convert.FromBase64String(info)));
            UserBaseInfoS2SDto userInfo = info.ToObject<UserBaseInfoS2SDto>();
            Guid eid = Guid.Empty;//错误代码

            #region 检查设备

            var equ = await _deviceService.GetDeviceAsync(facecode);
            if (equ == null)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{facecode}",
                    FromInfo = "固定贴纸,设备未找到",
                    UA = ua
                });
                //设备未找到
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.devnotfound, eid = eid });
            }
            //判断设备是否可用
            if (equ.Status == (int)DeviceStatus.Stop)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{facecode}",
                    FromInfo = "固定贴纸,设备已停止运行",
                    UA = ua
                });
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.deverror, eid = eid });
            }
            //判断设备是否激活
            if (!equ.ActiveTime.HasValue
                || equ.Status == DeviceStatus.UnActive)
            {
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = IDGen.NextID(),
                    Info = $"参数:{facecode}",
                    FromInfo = "固定贴纸,设备未激活",
                    UA = ua
                });
                //跳转到打开设备管理小程序的页面
                //获取设备绑定的设备管理小程序
                var order = await _orderService.GetDevMagOrderAsync(equ, userInfo);
                return RedirectToAction("bmini", new { sn = order.appid, page = order.content, n = order.NickName, h = order.HeadImg });
            }

            #endregion 检查设备

            //根据设备绑定的订单,跳转到不同的页面
            var orderinfo = await _orderService.GetOrderByStickerAsync(equ, userInfo, 2);
            if (orderinfo == null)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{facecode}",
                    FromInfo = "固定贴纸,未找到可用的订单",
                    UA = ua
                });
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.NoOrder, eid = eid });
            }
            //订单信息有误
            if (orderinfo.code > 0)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{facecode},返回:{orderinfo.code}",
                    FromInfo = "固定贴纸,获取订单失败",
                    UA = ua
                });
                return RedirectToAction("error", new { msg = orderinfo.code, eid = eid });
            }
            //保存记录
            await _orderService.InsertResultAsync(equ, userInfo, orderinfo);
            var jsondata = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{orderinfo.ToJson()}"));
            return RedirectToAction("f", new { info = jsondata });
        }

        /// <summary>
        /// 二维码展示页面
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<IActionResult> fAsync(string info = "")
        {
            var str = Encoding.UTF8.GetString(Convert.FromBase64String(info));
            var orderinfo = str.ToObject<OrderInfo>();
            //针对小程序,跳转路径携带fid参数表示用户粉丝唯一标识
            if (orderinfo.officetype == (int)OfficeType.MINI)
            {
                orderinfo.content = orderinfo.content.Contains("?") ? $"{orderinfo.content}&fid={orderinfo.WxFansId}" : $"{orderinfo.content}?fid={orderinfo.WxFansId}";
            }
            ViewData["orderinfo"] = orderinfo;
            //根据设备类型跳转到不同的页面
            string url = Request.AbsoluteUri();
            JsSdkUiPackage jssdkpackage = await _mPService.GetJsSdkUiPackageAsync(url);
            return View(jssdkpackage);
        }

        #endregion 固定贴纸处理

        #region 八电极绑定,暂时不用,20210904

        /// <summary>
        /// 绑定入口
        /// </summary>
        /// <param name="sn">设备机器码</param>
        /// <param name="t">设备类型</param>
        /// <returns></returns>
        [WeChatFilter]
        public IActionResult b(string sn, string t = "2")
        {
            //对参数进行base64编码
            var data = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{sn},{t}"));
            var url = $"{Configs.GetString("APIURL")}/Qr/body?data={data}";
            //对url进行base64编码
            url = Convert.ToBase64String(Encoding.UTF8.GetBytes(url));
            //跳转授权页面
            var state = "xbpage";//用于识别请求可靠性
            var redirecturl = $"{Configs.GetString("APIURL")}/Auth/page?r={url}";
            var rurl = OAuthApi.GetAuthorizeUrl(appId, redirecturl, state, OAuthScope.snsapi_userinfo);
            return Redirect(rurl);
        }

        /// <summary>
        /// 设备绑定页面,只针对wifi绑定版
        /// </summary>
        /// <param name="data"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        [WeChatFilter]
        public async Task<IActionResult> BodyAsync(string data, string info)
        {
            var ua = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].ToString();
            //对data进行base64解密
            var resultdata = Encoding.UTF8.GetString(Convert.FromBase64String(data));
            var arr = resultdata.Split(',');
            //数据格式不正确
            if (arr.Length != 2)
            {
                return View();
            }
            //内容为sn,t
            //二维码生成规格则：http://ybapi.ybhdmob.com/qr/b?sn=设备码&t=2
            //示例：http://ybapi.ybhdmob.com/qr/b?sn=b00001&t=2
            var ecode = arr[0];//格式:设备机器码
            var type = arr[1];//默认为2
            //对info进行base64解密，然后urldecode解码
            info = HttpUtility.UrlDecode(Encoding.UTF8.GetString(Convert.FromBase64String(info)));
            OAuthUserInfo userInfo = info.ToObject<OAuthUserInfo>();
            Guid eid = Guid.Empty;//错误代码

            #region 检查设备

            var equ = await _deviceService.GetDeviceByEcodeAsync(ecode);
            if (equ == null)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{resultdata}",
                    FromInfo = "八电极绑定页面,设备未找到",
                    UA = ua
                });
                //设备未找到
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.devnotfound, eid = eid });
            }
            //判断设备是否激活
            if (!equ.ActiveTime.HasValue
                //|| equ.EndTime < DateTime.Now
                || equ.Status == DeviceStatus.UnActive)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{resultdata}",
                    FromInfo = "八电极绑定页面,设备未激活",
                    UA = ua
                });
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.devnotactive, eid = eid });
                //跳转到设备激活页面
                //return Redirect($"/Device/Active?ecode={ecode}&type={type}");
            }
            //判断设备是否可用
            if (equ.Status == (int)DeviceStatus.Stop)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{resultdata}",
                    FromInfo = "八电极绑定页面,设备已停止运行",
                    UA = ua
                });
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.deverror, eid = eid });
            }

            #endregion 检查设备

            #region 生成要展示的公众号

            var order = await _orderService.GetAsync(equ, userInfo, 1, true);
            if (order == null || order.code != 0)
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{resultdata}",
                    FromInfo = "八电极绑定页面,获取订单失败",
                    UA = ua
                });
                //跳转到未找到可用公众号的错误页面
                return RedirectToAction("error", new { msg = order != null ? order.code : (int)ErrorInfoDesc.NoOrder, eid = eid });
            }
            //如果是关注公众号
            if (order.type == OrderType.Office)
            {
                //记录结果,返回二维码信息
                ViewData["ercode"] = order.content;
                ViewData["vrcode"] = order.vrcode;
                ViewData["officetype"] = order.officetype;
            }
            //如果是链接地址
            else if (order.type == OrderType.URL)
            {
                //直接跳转页面,要进行计费,待完善,20210317
                return Redirect(order.content);
            }
            else
            {
                eid = IDGen.NextID();
                await _capBus.PublishAsync("system.service.insertnoticelogger", new YB_NoticeLogger
                {
                    UserInfo = info,
                    Id = eid,
                    Info = $"参数:{resultdata}",
                    FromInfo = "八电极绑定页面,此订单类型不支持",
                    UA = ua
                });
                //跳转到此功能只能开发中
                return RedirectToAction("error", new { msg = (int)ErrorInfoDesc.develop, eid = eid });
            }

            #endregion 生成要展示的公众号

            return View();
        }

        /// <summary>
        /// 八电极数据结果展示
        /// </summary>
        /// <param name="d">
        /// sn|weight|height|lefthandimp|righthandimp|leftfootimp|rightfootimp|bodyimp
        /// </param>
        /// <returns></returns>
        [WeChatFilter]
        public async Task<IActionResult> brAsync(string d)
        {
            var arr = d.Split('|');
            int code = 0;
            if (arr.Length != 9)
            {
                code = 1;
            }
            else
            {
                string sn = arr[0];
                decimal weight = arr[1].ToDecimal();
                decimal height = arr[2].ToDecimal();
                int age = 20;
                GenderType sex = GenderType.Male;
                decimal lefthandimp = arr[3].ToDecimal();
                decimal righthandimp = arr[4].ToDecimal();
                decimal leftfootimp = arr[5].ToDecimal();
                decimal rightfootimp = arr[6].ToDecimal();
                decimal bodyimp = arr[7].ToDecimal();
                var bodyService = App.GetService<IBodyFatHelperService>();
                var bodyresult = await bodyService.CalcBody120FatAsync(weight, height, age, sex, lefthandimp, righthandimp, leftfootimp, rightfootimp, bodyimp);
                ViewData["sn"] = sn;
                ViewData["weight"] = weight;
                ViewData["height"] = height;
                ViewData["lefthandimp"] = lefthandimp;
                ViewData["righthandimp"] = righthandimp;
                ViewData["leftfootimp"] = leftfootimp;
                ViewData["rightfootimp"] = rightfootimp;
                ViewData["bodyimp"] = bodyimp;
                ViewData["age"] = age;
                ViewData["sex"] = sex == GenderType.Male ? "男" : "女";
                ViewData["bodyresult"] = bodyresult;
            }
            return View(code);
        }

        #endregion 八电极绑定,暂时不用,20210904

        /// <summary>
        /// 信息错误页面
        /// </summary>
        /// <param name="msg">错误信息代码</param>
        /// <param name="eid">错误代码ID</param>
        /// <returns></returns>
        [WeChatFilter]
        public IActionResult Error(int msg, string eid)
        {
            var errmsg = EnumHelper.GetEnumDictionary<ErrorInfoDesc>().FirstOrDefault(x => x.Key == msg).Value;
            ViewData["code"] = $"YBERROR-{eid}";
            ViewData["message"] = $"{errmsg}";
            return View();
        }

        /// <summary>
        /// 跳转到商户端小程序页面
        /// </summary>
        /// <param name="sn"></param>
        /// <param name="page">小程序路径</param>
        /// <param name="h">小程序昵称</param>
        /// <param name="n">小程序头像</param>
        /// <returns></returns>
        [WeChatFilter]
        public async Task<IActionResult> BMiniAsync(string sn, string page = "pages/index/index", string n = "", string h = "")
        {
            string url = Request.AbsoluteUri();
            var jssdkpackage = await _mPService.GetJsSdkUiPackageAsync(url);
            ViewData["username"] = sn;
            ViewData["page"] = page;
            ViewData["nickname"] = n;
            ViewData["headimg"] = h;
            return View(jssdkpackage);
        }

        /// <summary>
        /// 跳转到出入境小程序
        /// </summary>
        /// <returns></returns>
        [WeChatFilter]
        public async Task<IActionResult> crj()
        {
            string url = Request.AbsoluteUri();
            var jssdkpackage = await _mPService.GetJsSdkUiPackageAsync(url);
            //var jssdkpackage = new JsSdkUiPackage("", "", "", "");
            return View(jssdkpackage);
        }

        /// <summary>
        /// 测量二维码关注公众号之后的图文跳转页面
        /// </summary>
        /// <param name="openid">用户openid,base64加密</param>
        /// <param name="aid">用户appdi,base64加密</param>
        /// <param name="fansid">用户wxfansid</param>
        /// <param name="type">
        /// 1-认证的服务号关注事件,2-认证的服务号扫码事件,3-非认证关注事件,4-回复关键字,5-第一次打开落地页,6-非认证扫码事件
        /// </param>
        /// <param name="rid">记录ID</param>
        /// <returns></returns>
        [WeChatFilter]
        public async Task<IActionResult> sAsync(string openid, string aid, string fansid, int type, Guid? rid)
        {
            string url = Request.AbsoluteUri();
            string appid = Encoding.UTF8.GetString(Convert.FromBase64String(aid));
            string oid = Encoding.UTF8.GetString(Convert.FromBase64String(openid));
            //取绑定的小程序
            var orderinfo = await _orderService.HandlerResultSubscribeAsync(appid, oid, type, fansid, rid);
            var jssdkpackage = await _mPService.GetJsSdkUiPackageAsync(url);
            ViewData["username"] = orderinfo.appid;
            ViewData["page"] = orderinfo.content;
            ViewData["nickname"] = orderinfo.NickName;
            ViewData["headimg"] = orderinfo.HeadImg;
            return View(jssdkpackage);
        }

        /// <summary>
        /// 固定贴纸关注公众号之后的图文跳转页面
        /// </summary>
        /// <param name="openid">用户openid,base64加密</param>
        /// <param name="aid">用户appdi,base64加密</param>
        /// <param name="fansid">用户wxfansid</param>
        /// <param name="type">
        /// 1-认证的服务号关注事件,2-认证的服务号扫码事件,3-非认证关注事件,4-回复关键字,5-第一次打开落地页,6-非认证扫码事件
        /// </param>
        /// <param name="rid">测量记录ID</param>
        /// <returns></returns>
        [WeChatFilter]
        public async Task<IActionResult> tAsync(string openid, string aid, string fansid, int type, Guid? rid)
        {
            string url = Request.AbsoluteUri();
            string appid = Encoding.UTF8.GetString(Convert.FromBase64String(aid));
            string oid = Encoding.UTF8.GetString(Convert.FromBase64String(openid));
            var orderinfo = await _orderService.HandlerStickySubscribeAsync(appid, oid, type, fansid, rid);
            var jssdkpackage = await _mPService.GetJsSdkUiPackageAsync(url);
            ViewData["username"] = orderinfo.appid;
            ViewData["page"] = orderinfo.content;
            ViewData["nickname"] = orderinfo.NickName;
            ViewData["headimg"] = orderinfo.HeadImg;
            return View(jssdkpackage);
        }
    }
}