using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Ropin.Inspection.Api.Common;
using Ropin.Inspection.Api.Common.Options;
using Ropin.Inspection.Api.Common.Token;
using Ropin.Inspection.Api.Wx;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Ropin.Inspection.Model;
using Ropin.Inspection.Service.Interface;
using Ropin.Inspection.Model.ViewModel;
using Ropin.Inspection.Model.SearchModel;
using System.Net.Http.Headers;
using Ropin.Inspection.Common.Helper;
using Microsoft.AspNetCore.Http;
using Ropin.Inspection.Service;
using Ropin.Core.Extensions;
using Ropin.Inspection.Service.SYS.Interface;
using Ropin.Inspection.Model.ViewModel.SYS;
using UAParser;
using IPTools.Core;
using Microsoft.Extensions.Caching.Memory;
using Ropin.Core.Common;
using Ropin.Core.Extensions.Redis;

namespace Ropin.Inspection.Api.Controllers
{
    public class AccountController : BaseController
    {
        private readonly WXOptions _options;
        private readonly ITsysUserService _userService;
        private readonly ITokenHelper _tokenHelper = null;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ITmtnPushMsgToService _tmtnPushMsgToService;
        private readonly IPushMsgService _pushMsgService;
        private readonly ITsysRoleHandServices _roleHandServices;
        private readonly IsysLoginService _sysLoginService;
        private readonly RabbitMQModel _rabbitMQ;
        public AccountController(IOptionsMonitor<RabbitMQModel> rabbitMQ, IOptionsMonitor<WXOptions> options, IPushMsgService pushMsgService, ITmtnPushMsgToService tmtnPushMsgToService, IHttpClientFactory httpClientFactory, ITsysUserService userService, ITokenHelper tokenHelper, ITsysRoleHandServices roleHandServices, IsysLoginService sysLoginService, IRedisBasketRepository redisService)
        {
            _options = options.Get("WXOptions");
            _rabbitMQ = rabbitMQ.Get("RabbitMQModel");
            _userService = userService;
            _tokenHelper = tokenHelper;
            _httpClientFactory = httpClientFactory;
            _tmtnPushMsgToService = tmtnPushMsgToService;
            _pushMsgService = pushMsgService;
            _roleHandServices = roleHandServices;
            _sysLoginService = sysLoginService;
            RedisLimitUserLogin._redisConnection = redisService;
        }
        /// <summary>
        /// 微信
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetWX/{loginCode}")]
        [AllowAnonymous]
        public async Task<ApiResult> GetWX(string loginCode)
        {
            if (string.IsNullOrEmpty(loginCode))
            {
                return new ApiResult(ReturnCode.ArgsError, "loginCode空值");
            }

            Code2Session session = null;
            string url = string.Format(_options.Code2Session, _options.AppId, _options.Secret, loginCode);

            //using (var client = _httpClientFactory.CreateClient())
            //{
            //    using var res = client.GetAsync(url);
            //    if (res.Result.StatusCode == System.Net.HttpStatusCode.OK)
            //    {
            //        var str = res.Result.Content.ReadAsStringAsync().Result;
            //        session = JsonConvert.DeserializeObject<Code2Session>(str);
            //    }
            //}


            using (var client = _httpClientFactory.CreateClient())
            {
                var requestt = new HttpRequestMessage(HttpMethod.Get, url);
                requestt.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                var response = await client.SendAsync(requestt);
                if (response.IsSuccessStatusCode)
                {
                    var strReturn = await response.Content.ReadAsStringAsync();
                    session = JsonConvert.DeserializeObject<Code2Session>(strReturn);
                }
                Console.WriteLine(response);
            }


            if (session == null)
            {
                return new ApiResult(ReturnCode.LoginError, "session空值");
            }

            if (string.IsNullOrEmpty(session.Openid))
            {
                return new ApiResult(ReturnCode.LoginError, "Openid空值");
            }
            //session.Openid = "ox1D95f2CfZQVkIqYTsNgrwBpKD8";
            //小程序返回的Openid验证
            TsysUserSearchModel userSearchModel = new TsysUserSearchModel { WxOpenId = session.Openid };
            TsysUserViewModel user =  _userService.GetUser(userSearchModel);

            if (null == user)
            {
                LoginReturnInfo ReInfo = new LoginReturnInfo { ReturnCode = 101, OpenId = session.Openid };
                //return new ApiResult<string>(session.Openid, ReturnCode.PasswordLogin);
                return new ApiResult<LoginReturnInfo>(ReInfo, ReturnCode.Success);
            }
            TsysUserDetailViewModel user2 = await _userService.GetUserDetailByAsync(new LoginModel { Mobile = user.C_Mobile, Password = user.C_Password });
            var token = _tokenHelper.CreateToken(user2);
            if (null == token)
            {
                return new ApiResult(ReturnCode.TokenError, "获取Token异常");
            }
            LoginReturnInfo Info;
            //if (user.C_Password == "e10adc3949ba59abbe56e057f20f883e")
            //    Info = new LoginReturnInfo { ReturnCode = 102, ReturnToken = token,OpenId = session.Openid };
            //else
                Info = new LoginReturnInfo { ReturnCode = 100, ReturnToken = token, OpenId = session.Openid };

            // 获取用户的IP地址
            string ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
            // 获取浏览器信息
            string userAgent = Request.Headers["User-Agent"].ToString();
            var clientAgent = Parser.GetDefault().Parse(userAgent);
            var browser = $"{clientAgent.UA.Family} {clientAgent.UA.Major}.{clientAgent.UA.Minor} / {clientAgent.Device.Family}";
            var os = $"{clientAgent.OS.Family} {clientAgent.OS.Major} {clientAgent.OS.Minor}";
            (string ipLocation, double? longitude, double? latitude) = GetIpAddress(ipAddress);
            sysLoginViewModel sysLogin = new sysLoginViewModel();
            sysLogin.C_IP = ipAddress;
            sysLogin.C_UserName = user.C_Name;
            sysLogin.C_AccountNumber = user.C_Mobile;
            sysLogin.C_Type = "SYS_PRIV_MODULE_002";
            sysLogin.C_Address = ipLocation;
            sysLogin.C_Browser = browser;
            sysLogin.C_OS = os;
            sysLogin.C_Role = user.UserRole.ToString();
            sysLogin.C_LicenseCode = user.C_LicenseCode;
            sysLogin.C_CreateBy = user.C_UserID.ToString();
            sysLogin.D_CreateOn = DateTime.Now;
            sysLogin.C_Status = "1";
            sysLogin.C_OperationInfo = "登录成功!";
            await _sysLoginService.CreateOneAsync(sysLogin);
            return new ApiResult<LoginReturnInfo>(Info, ReturnCode.Success);
        }
        
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        [HttpPost("Login")]
        [AllowAnonymous]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public async Task<ApiResult> Login(LoginModel viewModel)
        {
            try
            {
                var IsUser = await _userService.IsExistByMobileAsync(viewModel.Mobile);
                if (!IsUser)
                {
                    return new ApiResult(ReturnCode.LoginError, "账户不存在!");
                }
                var isLock = await RedisLimitUserLogin.IsForbidden(viewModel.Mobile);
                if (isLock)
                {
                    return new ApiResult(ReturnCode.LoginError, $"账户已锁定,请{RedisLimitUserLogin.LockTime}分钟后在试");
                }

                // 获取用户的IP地址
                string ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
                // 获取浏览器信息
                string userAgent = Request.Headers["User-Agent"].ToString();
                var client = Parser.GetDefault().Parse(userAgent);
                var browser = $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
                var os = $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
                (string ipLocation, double? longitude, double? latitude) = GetIpAddress(ipAddress);
                sysLoginViewModel sysLogin = new sysLoginViewModel();
                sysLogin.C_IP = ipAddress;
                sysLogin.C_Address = ipLocation;
                sysLogin.C_Browser = browser;
                sysLogin.C_OS = os;
                sysLogin.C_AccountNumber = viewModel.Mobile;
                sysLogin.C_Type = viewModel.PrivModule;
                sysLogin.D_CreateOn = DateTime.Now;

                #region 测试
                //new WeChatHelper(_httpClientFactory).PushMessageToUser();
                #endregion



                var user = await _userService.GetUserDetailByAsync(viewModel);
                if (null == user)
                {
                    int loseNumber=await RedisLimitUserLogin.SetFailCounter(viewModel.Mobile);
                    var userMode = await _userService.GetByMobileAsync(viewModel.Mobile);
                    sysLogin.C_UserName = userMode?.C_Name;
                    sysLogin.C_Role = userMode?.UserRole.ToString();
                    sysLogin.C_LicenseCode = userMode?.C_LicenseCode;
                    sysLogin.C_CreateBy = userMode?.C_UserID.ToString();
                    sysLogin.C_Status = "0";
                    string msg = $"账号或密码不正确,输入错误{loseNumber} 次!";
                    if (loseNumber== RedisLimitUserLogin.MaxAttempts)
                    {
                        msg = $"错误{loseNumber}次,{RedisLimitUserLogin.LockTime}分钟后再许可登录!";
                    }
                    sysLogin.C_OperationInfo = msg;
                    await _sysLoginService.CreateOneAsync(sysLogin);
                    return new ApiResult(ReturnCode.LoginError, msg);
                }
                RedisLimitUserLogin.UnLock(viewModel.Mobile);
                if (user.RoleTypePrivS==null|| user.RoleTypePrivS.Count()==0)
                {
                    return new ApiResult(ReturnCode.LoginPriv, "没有权限");
                }
                if (!string.IsNullOrEmpty(viewModel.OpenId))
                {
                    await _userService.UpdateUserOpenIdAsync(user.C_UserID, viewModel.OpenId);
                }
                Guid roleId= Guid.Parse(user.RoleIds);
                var roleHand = await _roleHandServices.GetRoleHandListAsync(roleId);
                user.RoleHandList = roleHand;
                var token = _tokenHelper.CreateToken(user);

                sysLogin.C_UserName = user.C_Name;
                sysLogin.C_Role = user.RoleIds;
                sysLogin.C_LicenseCode = user.C_LicenseCode;
                sysLogin.C_CreateBy = user.C_UserID.ToString();

                if (null == token)
                {
                    sysLogin.C_Status = "0";
                    sysLogin.C_OperationInfo = "登录失败!";
                    await _sysLoginService.CreateOneAsync(sysLogin);
                    return new ApiResult(ReturnCode.TokenError, "获取Token异常");
                }
                sysLogin.C_Status = "1";
                sysLogin.C_OperationInfo = "登录成功!";
                await _sysLoginService.CreateOneAsync(sysLogin);

                return new ApiResult<ComplexToken>(token, ReturnCode.Success);
            }
            catch (Exception ex)
            {
                return new ApiResult(ReturnCode.GeneralError, ex.Message);
            }
            
        }
        /// <summary>
        /// 登出
        /// </summary>
        /// <returns></returns>
        [HttpPost("LogOut")]
        public async Task<ApiResult> LogOutByAsync()
        {
            try
            {
                // 获取用户的IP地址
                string ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
                // 获取浏览器信息
                string userAgent = Request.Headers["User-Agent"].ToString();
                var client = Parser.GetDefault().Parse(userAgent);
                var browser = $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
                var os = $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
                (string ipLocation, double? longitude, double? latitude) = GetIpAddress(ipAddress);
                sysLoginViewModel sysLogin = new sysLoginViewModel();
                sysLogin.C_IP = ipAddress;
                sysLogin.C_Type = "";
                sysLogin.C_Address = ipLocation;
                sysLogin.C_Browser = browser;
                sysLogin.C_OS = os;
                sysLogin.C_Status = "1";
                sysLogin.C_OperationInfo = "退出系统!";
                await _sysLoginService.CreateOneAsync(sysLogin);

                await _userService.LogOutByAsync();
                return new ApiResult(ReturnCode.Success);
            }
            catch (Exception ex)
            {
                return new ApiResult(ReturnCode.GeneralError, ex.Message);
            }
        }
        /// <summary>
        /// 测试推送消息,通过Token(可行)
        /// </summary>
        /// <returns></returns>
        [HttpPost("PushMessageByTokenAsync/{userWechatId}/{msg}/{token}")]
        [AllowAnonymous]
        public ApiResult PushMessageByTokenAsync(string userWechatId, string msg, string token)
        {
            try
            {
                //var content = new
                //{
                //    thing2 = new { value = "niu" ?? "" },
                //    time4 = new { value = DateTime.Now.ToString("yyyy-MM-dd hh:mm") },
                //    thing5 = new { value = "异常" ?? "" },
                //    thing6 = new { value = "大门损坏" ?? "" },
                //    thing9 = new { value = msg ?? "" }
                //};
                var content = new
                {
                    character_string1 = new { value = "123456" ?? "" },
                    thing2 = new { value = "niu" ?? "" },
                    thing16 = new { value = "大门损坏" ?? "" },
                    time5 = new { value = DateTime.Now.ToString("yyyy-MM-dd hh:mm") },                   
                    thing6 = new { value = "msg" ?? "" }
                };
                new WeChatHelper(_httpClientFactory).SubMessageToUser(userWechatId,token,null, content);
                return new ApiResult(ReturnCode.Success);
            }
            catch (Exception ex)
            {
                return new ApiResult(ReturnCode.GeneralError, ex.Message);
            }
        }
        /// <summary>
        /// 测试推送消息,通过Wechat(可行)
        /// </summary>
        /// <param name="userWechatId"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        [HttpPost("PushMessageByWechatIdAsync/{userWechatId}/{msg}")]
        [AllowAnonymous]
        public ApiResult PushMessageByWechatIdAsync(string userWechatId, string msg)
        {
            try
            {
                //var content = new
                //{
                //    character_string1 = new { value = "123456" ?? "" },
                //    thing2 = new { value = "niu" ?? "" },
                //    thing16 = new { value = "大门损坏" ?? "" },
                //    time5 = new { value = DateTime.Now.ToString("yyyy-MM-dd hh:mm") },
                //    thing6 = new { value = msg ?? "" }
                //};
                var content = new
                {
                    character_string1 = new { value = "123456" ?? "" },
                    time2 = new { value = DateTime.Now.ToString("yyyy-MM-dd hh:mm") },
                    short_thing3 = new { value = "告警类型" ?? "" }
                };
                string templateId = WXConstModel.WatchHealthAlarm_TemplateId;
                new WeChatHelper(_httpClientFactory).PushMessageToUser(new List<string>() { userWechatId }, content,templateId);
                return new ApiResult(ReturnCode.Success);
            }
            catch (Exception ex)
            {
                return new ApiResult(ReturnCode.GeneralError, ex.Message);
            }
        }
        /// <summary>
        /// 测试推送消息,通过devId(可行)
        /// </summary>
        /// <param name="devId"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        [HttpPost("PushMessageByDevIdAsync/{msg}/{devId}")]
        [AllowAnonymous]
        [HttpIdempotent(WaitMillisecond = 20000)]
        public async Task<ApiResult> PushMessageByDevIdAsync(string msg, string devId)
        {
            try
            {
                //_tmtnPushMsgToService.PushAlarmMsgAsync(new TpushMsgModel
                //{
                //    C_DevStoreCode = devId,
                //    C_MsgTypeCode = "MSG_TYPE_001",
                //    Msg = msg,
                //    Subject = "压力表维修通知"
                //});
                await _pushMsgService.PushAlarmMsgAsync(new TpushMsgModel
                {
                    C_DevStoreCode = devId,
                    C_MsgTypeCode = "MSG_TYPE_023",
                    Msg = msg,
                    Subject = "测试推送消息",
                    DevNumber = "boxId:",
                    DevName = "sadf",
                });
                return new ApiResult(ReturnCode.Success);
            }
            catch (Exception ex)
            {
                return new ApiResult(ReturnCode.GeneralError, ex.Message);
            }
        }
        /// <summary>
        /// 测试发送邮件
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        [HttpPost("EmailTest/{email}")]
        [AllowAnonymous]
        public async Task<ApiResult> EmailTest(string email)
        {
            string msg = "<p><td>设备编号:</td>20250226</p>" +
                                    "<p><td>设备名称:</td>设备DevName</p>" +
                                    "<p><td>消息内容:</td>测试Email发送消息</p>"
                                    ;
            var bols = EmailHelper.SendEmail(email, "测试发送邮件", "测试", msg);
            if (bols)
            {
                return new ApiResult(ReturnCode.Success);
            }
            else
            {
                return new ApiResult(ReturnCode.GeneralError);
            }
        }
        /// <summary>
        /// 多次提交
        /// </summary>
        /// <param name="orderNo"></param>
        /// <returns></returns>
        [HttpPost("OrderAsync/{orderNo}")]
        [HttpIdempotent(WaitMillisecond = 10000, CacheMillisecond = 3000)]
        [AllowAnonymous]
        public async Task<IActionResult>  OrderAsync(string orderNo)
        {
            //TODO
            //return  Content("你好");
            return await Task.FromResult(Ok(new
            {
                TotalCount = 10,
                TotalPages = 2,
                Orders = orderNo
            })) ;
        }
        /// <summary>
        /// 公共推送
        /// </summary>
        /// <param name="pushMsg"></param>
        /// <returns></returns>
        [HttpPost("PublicPushMessage")]
        [AllowAnonymous]
        public async Task<ApiResult> PublicPushMessage(TpushMsgModel pushMsg)
        {
            if (pushMsg == null || string.IsNullOrEmpty(pushMsg.C_MsgTypeCode) || string.IsNullOrEmpty(pushMsg.C_DevStoreCode))
            {
                return new ApiResult(ReturnCode.ArgsError);
            }
            try
            {
                _rabbitMQ.QueueName = "rab.video.record.mqtt"; //消息队列名称
                bool  result= await _pushMsgService.PushAlarmMsgAsync(pushMsg,pushMsg.Subject, _rabbitMQ);
                if (result)
                {
                    return new ApiResult(ReturnCode.Success);
                }
                else
                {
                    return new ApiResult(ReturnCode.GeneralError);
                }
            }
            catch (Exception ex)
            {
                return new ApiResult(ReturnCode.GeneralError, ex.Message);
            }
        }
        
        /// <summary>
        /// 解析IP地址
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        [NonAction]
        internal static (string ipLocation, double? longitude, double? latitude) GetIpAddress(string ip)
        {
            try
            {
                var ipInfo = IpTool.Search(ip);
                var addressList = new List<string>() { ipInfo.Country, ipInfo.Province, ipInfo.City, ipInfo.NetworkOperator };
                return (string.Join("|", addressList.Where(it => it != "0").ToList()), ipInfo.Longitude, ipInfo.Latitude); // 去掉0并用|连接
            }
            catch(Exception ex)
            {
                // 不做处理
            }
            return ("未知", 0, 0);
        }
    }
}