using ASHermed.SinoInterface.Api.ContractModel.Coupon.Entity;
using ASHermed.SinoInterface.Api.ContractModel.Coupon.Model;
using ASHermed.SinoInterface.Api.IRepository;
using ASHermed.SinoInterface.Api.IRepository.App;
using ASHermed.SinoInterface.Api.IService;
using ASHermed.SinoInterface.Enum.App;
using ASHermed.SinoInterface.Tools;
using Newtonsoft.Json;
using PoJun.Util.Maps;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using ASHermed.SinoInterface.ContractModel;
using ASHermed.SinoInterface.Api.ContractModel.App.Entity;
using ASHermed.SinoInterface.Api.ContractModel.App;

namespace ASHermed.SinoInterface.Api.Service
{
    public class CouponService : BaseService, ICouponService
    {
        IOnlineCouponPubUserRepository _onlineCouponPubUserRepository;
        IOnlineCouponlogsRepository _onlineCouponlogsRepository;
        IOnlineCouponRepository _onlineCouponRepository;
        RedisHelperClient _redisHelper;
        IPubPatInfoRepository _pubPatRepository;
        HttpClient _httpClient;
        IDicDoctorRepository _dicDoctorRepository;
        IDicMapDeptDoctorRepository _dicMapDeptDoctorRepository;
        IAptService _aptService;
        IPubMessageService _pubMessageService;
        IVerifyCodeLogService _verifyCodeLogService;
        IDicCouponRepository _dicCouponRepository;
        IPubCouponFlowRepository _pubCouponFlowRepository;
        IIntegralFlowRepository _integralFlowRepository;
        IPubUserInfoRepository _pubUserInfoRepository;

        public CouponService(IOnlineCouponPubUserRepository onlineCouponPubUserRepository, IOnlineCouponlogsRepository onlineCouponlogsRepository, IOnlineCouponRepository onlineCouponRepository, RedisHelperClient redisHelper, IPubPatInfoRepository pubPatInfoRepository, IHttpClientFactory httpClientFactory, IDicDoctorRepository dicDoctorRepository, IDicMapDeptDoctorRepository dicMapDeptDoctorRepository, IAptService aptService, IPubMessageService pubMessageService, IVerifyCodeLogService verifyCodeLogService, IDicCouponRepository dicCouponRepository, IPubCouponFlowRepository pubCouponFlowRepository, IIntegralFlowRepository integralFlowRepository, IPubUserInfoRepository pubUserInfoRepository)
        {
            _onlineCouponPubUserRepository = onlineCouponPubUserRepository;
            _onlineCouponlogsRepository = onlineCouponlogsRepository;
            _onlineCouponRepository = onlineCouponRepository;
            _redisHelper = redisHelper;
            _pubPatRepository = pubPatInfoRepository;
            _httpClient = httpClientFactory.CreateClient(HttpClientConst.AdminBase_CLIENT_NAME);
            _dicDoctorRepository = dicDoctorRepository;
            _dicMapDeptDoctorRepository = dicMapDeptDoctorRepository;
            _aptService = aptService;
            _pubMessageService = pubMessageService;
            _verifyCodeLogService = verifyCodeLogService;
            _dicCouponRepository = dicCouponRepository;
            _pubCouponFlowRepository = pubCouponFlowRepository;
            _integralFlowRepository = integralFlowRepository;
            _pubUserInfoRepository = pubUserInfoRepository;
        }

        /// <summary>
        /// 同步患者优惠券，更新优惠券过期信息
        /// </summary>
        /// <param name="patId"></param>
        public void SynchronizationCouponStatus(int patId)
        {
            List<int> patids = new List<int>();
            patids.Add(patId);
            var usecoupon = _onlineCouponPubUserRepository.GetOnlineCouponPubUserListForPatId(patids, (int)CouponUserEnum.All);
            var couponls = _onlineCouponRepository.GetOnlineCouponList(usecoupon.Select(w => w.CouponId).ToList(), 1);
            var ids = new List<int>();
            //只有未使用的优惠券需要同步状态为已过期
            foreach (var item in usecoupon.Where(w => w.Status == (int)CouponUserEnum.NotUsed))
            {
                var coupon = couponls.Where(w => w.Id == item.CouponId).FirstOrDefault();
                if (coupon != null)
                {
                    if (item.CreateTime.AddDays(coupon.EffectiveTime) < DateTime.Now)
                    {
                        ids.Add(item.Id);
                    }
                }
            }
            if (ids.Any())
                _onlineCouponPubUserRepository.UpdateCouponPubUserStatus(ids, (int)CouponUserEnum.Expired);
        }

        /// <summary>
        /// 获取用户优惠券
        /// </summary>
        /// <param name="patid"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public List<CouponUserView> GetPatConponForPatId(List<int> patid, int language)
        {
            List<CouponUserView> response = new List<CouponUserView>();
            var usercoupon = _onlineCouponPubUserRepository.GetOnlineCouponPubUserListForPatId(patid, (int)CouponUserEnum.NotUsed);
            //获取优惠券详情
            var coupon = _onlineCouponRepository.GetOnlineCouponList(usercoupon.Select(w => w.CouponId).ToList(), language);
            foreach (var item in usercoupon)
            {
                if (coupon.Where(w => w.Id == item.CouponId).FirstOrDefault() != null)
                {
                    CouponUserView model = new CouponUserView();
                    model = item.MapTo<CouponUserView>();
                    model.ConponDetail = coupon.Where(w => w.Id == item.CouponId).FirstOrDefault();
                    response.Add(model);
                }
            }
            return response;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="patId"></param>
        /// <param name="couponNames"></param>
        public void IssueCoupons(int patId, List<Online_Coupon> couponNames)
        {
            List<int> patids = new List<int>();
            patids.Add(patId);
            //创建优惠券
            CreateCoupon(couponNames);

            var couponlist = _onlineCouponRepository.GetOnlineCouponForName(couponNames.Select(w => w.Name).ToList());

            //给患者发券
            foreach (var item in couponNames)
            {
                var lkhzx = couponlist.Where(w => w.Name == item.Name).FirstOrDefault();
                if (lkhzx.StartTime < DateTime.Now && lkhzx.EndTime >= DateTime.Now)
                {
                    if (!_onlineCouponPubUserRepository.GetOnlineCouponPubUserListForPatId(patids, (int)CouponUserEnum.NotUsed).Where(w => w.CouponId == lkhzx.Id).Any())
                    {
                        if (item.Name == "视频咨询券")
                        {
                            var conpon = _onlineCouponPubUserRepository.GetUserCouponsNoStatus(patId);
                            if (!conpon.Where(w => w.CouponId == lkhzx.Id).Any())
                            {
                                SendCoupon(lkhzx, patId);
                            }
                        }
                        else //视频咨询券只发一次，其他券只要用完了就发，用于写死的活动
                        {
                            SendCoupon(lkhzx, patId);
                        }
                    }
                }
            }

        }

        public void SendCoupon(Online_Coupon lkhzx, int patId)
        {
            var key = "Conpon:Quota" + lkhzx.Id;
            if (_redisHelper.KeyExistsAsync(key).Result)
            {
                var quota = _redisHelper.StringDecrementAsync(key).Result;
                if ((int)quota > 0)
                {
                    _onlineCouponPubUserRepository.InsertCouponPubUser(new ContractModel.Coupon.Entity.Online_CouponPubUser
                    {
                        PubUserId = GetBaseUserInfo().ID,
                        CouponId = lkhzx.Id,
                        Money = lkhzx.Money,
                        CreateTime = DateTime.Now.AddMinutes(-1),
                        FullMoney = lkhzx.FullMoney,
                        Status = (int)CouponUserEnum.NotUsed,
                        PatId = patId
                    });
                }
                _onlineCouponRepository.UpdateCouponQuota(lkhzx.Id, (int)quota);
            }
        }

        /// <summary>
        /// 创建优惠券
        /// </summary>
        /// <param name="couponNames"></param>
        public void CreateCoupon(List<Online_Coupon> couponNames)
        {
            var couponls = _onlineCouponRepository.GetOnlineCouponForName(couponNames.Select(w => w.Name).ToList());

            foreach (var item in couponNames)
            {
                //不存在创建活动
                if (!couponls.Where(w => w.Name == item.Name).Any())
                {
                    var id = _onlineCouponRepository.InsertCoupon(item);
                    var key = "Conpon:Quota" + id; ;
                    var redisres = _redisHelper.StringIncrementAsync(key, 999999).Result;
                }
            }
        }

        /// <summary>
        /// 获取写死的活动配置
        /// </summary>
        /// <param name="patId"></param>
        /// <returns></returns>
        public List<Online_Coupon> GetCoupons(int patId)
        {
            List<Online_Coupon> couponNames = new List<Online_Coupon>();
            var pat = _pubPatRepository.SelectById(patId);
            //老用户专享优惠只针对于在TC有过就诊记录的患者
            var tcrecord = _httpClient.GetAsync("Admin/Api/User/GetAllPatDetailForPat?patId=" + patId + "&type=All&Isfilter=false").Result;
            if (tcrecord.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var tcres = JsonConvert.DeserializeObject<BaseResponse<List<HistoryOfConsultation>>>(tcrecord.Content.ReadAsStringAsync().Result);
                if (tcres != null && tcres.Data.Any())
                {
                    couponNames.Add(new Online_Coupon
                    {
                        Type = (int)CouponTypeEnum.NoThreshold,
                        Name = "老客户专享优惠",
                        NameEN = "Exclusive discount for old customers",
                        Img = "",
                        StartTime = DateTime.Now,
                        EndTime = DateTime.Now.AddYears(10),
                        Money = 200,
                        Status = (int)CouponEnum.Effective,
                        Remarks = "老客户专享优惠",
                        CreateTime = DateTime.Now,
                        FullMoney = 0,
                        DocIds = "",
                        Quota = 999999,
                        AptType = "2",
                        DeptId = "",
                        IsDelete = false,
                        EffectiveTime = 365
                    });

                    //免费儿科视频咨询券 TC有过就诊记录的患者，年龄为小于等于14岁
                    //获取儿科在TC那边配置的名称，用于筛选儿科视频咨询券
                    List<string> deptname = new List<string>();
                    var hismapdept = _httpClient.GetAsync("Admin/Api/Dept/GetMapHisDept?deptId=1055").Result;
                    if (hismapdept.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        var dept = JsonConvert.DeserializeObject<BaseResponse<List<Dic_Map_His_Dept>>>(hismapdept.Content.ReadAsStringAsync().Result);
                        foreach (var item in dept.Data)
                        {
                            deptname.Add(item.HisDeptName);
                        }
                    }
                    if (tcres.Data.Where(w => deptname.Contains(w.DeptName)).Any() && !string.IsNullOrEmpty(pat.Birthday))
                    {
                        if (DateTime.Parse(pat.Birthday).GetAgeByBirth() <= 14)
                        {
                            couponNames.Add(new Online_Coupon
                            {
                                Type = (int)CouponTypeEnum.Free,
                                Name = "视频咨询券",
                                NameEN = "Video Consultation",
                                Img = "",
                                StartTime = DateTime.Parse("2021-06-01"),
                                EndTime = DateTime.Parse("2021-06-30"),
                                Money = 0,
                                Status = (int)CouponEnum.Effective,
                                Remarks = "仅限儿科使用1次",
                                CreateTime = DateTime.Now,
                                FullMoney = 0,
                                DocIds = "",
                                Quota = 999999,
                                AptType = "1",
                                DeptId = "1055",
                                IsDelete = false,
                                EffectiveTime = 30,
                                Content = @"1.       领取日期：2021年6月1日-6月30日
            2.       领取条件：曾在曜影医疗旗下门诊部儿科就诊过，每位用户限领1次。
            3.       领取方式：在曜影医疗APP中绑定就诊人后方可领取。
            4.       使用日期：领取后30天内可用。
            5.       使用方式：登录曜影医疗APP，进入“互联网医院”进行预约，优惠券将在预约支付页面自动抵扣。
            6.       如有任何问题，可在曜影医疗APP内咨询客服小影。
            7.       在法律允许的范围内，本活动解释权归曜影医疗所有。",
                                ContentEN = @"1、Available date：1st June, 2021 – 31st June, 2021
            2、Qualification ： Any patient below 14yrs who have visit a pediatrician in-person in SinoUnited Health. Each customer is limited to 1 voucher.
            3、Get Voucher：Add Patient Information on Family Members in SinoUnited Health App
            4、How to use：Within 30 days after receiving the voucher
            5. Usage: Log into SinoUnited Health App, tap Virtual Clinic to make an appointment, and the voucher will be automatically deducted on the payment page.
            6. If you have any problem, please contact customer service Ying on the APP
            7. To the extent permitted by law, the right to interpret this activity belongs to SinoUnited Health",
                                MoneyRemark = "免费",
                                MoneyRemarkEN = "Free",
                                RemarksEN = "Free Pediatric Video Consultation *1",
                                TermOfValidity = "领取后30天内有效",
                                TermOfValidityEN = "Valid within 30 days after receiving"
                            });
                        }
                    }
                }
            }
            return couponNames;
        }

        /// <summary>
        /// 计算当前优惠券优惠的金额
        /// </summary>
        /// <param name="couponUser"></param>
        /// <param name="orderprice"></param>
        /// <param name="ret"></param>
        /// <returns></returns>
        public decimal CalculationPrice(CouponUserView couponUser, decimal orderprice, out bool ret)
        {
            ret = true;
            decimal price = 0M;
            //核销优惠券
            switch (couponUser.ConponDetail.Type)
            {
                case (int)CouponTypeEnum.NoThreshold:
                    price = couponUser.Money;
                    break;
                case (int)CouponTypeEnum.FullReduction:
                    if (orderprice >= couponUser.FullMoney)
                    {
                        price = couponUser.Money;
                    }
                    else { ret = false; }
                    break;
                case (int)CouponTypeEnum.Superposition:
                    if (orderprice >= couponUser.FullMoney)
                    {
                        price = couponUser.Money;
                    }
                    else { ret = false; }
                    break;
                case (int)CouponTypeEnum.Discount:
                    price = Math.Round(orderprice * couponUser.Money, 2);
                    break;
                case (int)CouponTypeEnum.Free:
                    price = orderprice;
                    break;
            }
            return price;
        }

        /// <summary>
        /// 获取当前订单预约医生价格
        /// </summary>
        /// <param name="apttype"></param>
        /// <param name="deptid"></param>
        /// <param name="docid"></param>
        /// <param name="language"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public decimal GetOrderPrice(int apttype, int deptid, int docid, int language, string key, string type = "sino")
        {
            decimal price = 0M;
            if (apttype == 1)
            {
                var aptList = _dicDoctorRepository.GetVideoDoctorByDept(deptid, docid, language, key);
                if (aptList != null)
                {
                    price = aptList.FirstOrDefault().Price;
                }

            }
            if (apttype == 2)
            {
                if (type == null || type == "sino")
                {
                    var aptList = _dicDoctorRepository.GetReVisitDoctorByDept(deptid, docid, language, key);
                    if (aptList != null)
                    {
                        price = aptList.FirstOrDefault().Price;
                    }
                }
                if (type == "cigna")
                {
                    var aptList = _dicDoctorRepository.GetInsurDoctorByDept(3, deptid, docid, language, key);
                    if (aptList != null)
                    {
                        price = aptList.FirstOrDefault().Price;
                    }
                }

            }
            return price;
        }

        /// <summary>
        /// 验证优惠券医生能否使用
        /// </summary>
        /// <returns></returns>
        public bool VerificationCouponDoc(string docids, string deptids, string orderdocid, int apttype)
        {
            bool docpass = true;
            //判断当前优惠券使用医生是否正确
            if (!string.IsNullOrEmpty(docids))
            {
                if (!docids.Contains(orderdocid))
                {
                    docpass = false;
                }
                else
                {
                    docpass = true;
                }
            }
            //对比科室
            if (!string.IsNullOrEmpty(deptids))
            {
                List<int> IDs = new List<int>();
                deptids.Split(',').ToList().ForEach(e =>
                {
                    IDs.Add(int.Parse(e));
                });
                var doc = _dicMapDeptDoctorRepository.GetDocIdsForDeptIds(IDs, apttype);
                if (!doc.Contains(int.Parse(orderdocid)))
                {
                    docpass = false;
                }
                else
                {
                    docpass = true;
                }
            }
            return docpass;
        }

        public bool VerificationCouponTime(DateTime starttime, int effectiveTime, DateTime effectiveDateTime)
        {
            starttime = starttime.AddSeconds(-1);
            if (effectiveDateTime != DateTime.MinValue || effectiveDateTime != DateTime.MaxValue)
            {
                if ((starttime <= DateTime.Now && starttime.AddDays(effectiveTime) >= DateTime.Now) || effectiveDateTime >= DateTime.Now)
                {
                    return true;
                }
            }
            else
            {
                if (!(starttime <= DateTime.Now && starttime.AddDays(effectiveTime) >= DateTime.Now))
                {
                    return true;
                }
            }

            return false;
        }

        public bool PediatricsConpon()
        {
            //RSAHelper.RsaTest();
            //私钥
            var provider1 = CignaHelper.GetPrivateKey("D:\\user-rsa.pfx", "sino2556");
            //provider1.Decrypt();
            //公钥
            var provider2 = CignaHelper.GetPublicKey("D:\\public-rsa.cer");
            string data = @"RSA 是常用的非对称加密算法。最近使用时却出现了“不正确的长度”的异常，研究发现是由于待加密的数据超长所致。";
            var res = CignaHelper.Encrypt(data, provider2);
            res = CignaHelper.Decrypt(res, provider1);
            //var pkey = rsa.ReadPublicKey("D:\\privateKey");



            //var userList = _pubPatRepository.GetAptByCondition();
            //foreach (var item in userList)
            //{
            //    if (item.Language == 2)
            //    {
            //        _pubMessageService.SendPediatricsWxMsg(item.Open_ID, "【Special Offer】 Free pediatric video consultation once", "Pediatrics", "Can be checked on SinoUnited Health App", "High-quality Medical Care at Your Fingertips! Tap to get your privilege", "https://shop42729919.youzan.com/v2/feature/G2VIKYpjxl");
            //    }
            //    else
            //    {
            //        _pubMessageService.SendPediatricsWxMsg(item.Open_ID, "【六一福利】领取免费儿科视频咨询1次，在家也能问医生啦", "儿科医生可约", "进入曜影医疗APP查看", "高品质医疗触手可及！点击领取儿科咨询福利", "https://shop42729919.youzan.com/v2/feature/HcwRf2gAXy");
            //    }
            //}
            return true;
        }

        public List<ReceivedCoupon> FindReceivedByPhone(string phone, int fID)
        {
            return _dicCouponRepository.SelectReceivedCouponByPhone(phone, fID);
        }

        public string ReceiveCoupon(Pub_Coupon_Flow pubCouponFlow)
        {
            if (pubCouponFlow.Receiptor_Phone == pubCouponFlow.Sharing_Phone)
            {
                return "不能领取自己分享的优惠券";
            }

            // 查询优惠券字典
            Dic_Coupon coupon = CanCouponReceived(pubCouponFlow.Coupon_Id, pubCouponFlow.Receiptor_Phone);
            if (coupon == null)
            {
                return "该优惠券无法使用";
            }
            int flowId = 0;
            string sharingPhone = pubCouponFlow.Sharing_Phone;
            if (!string.IsNullOrEmpty(sharingPhone))
            {
                Pub_Integral_Flow pubIntegralFlow = GainSharingIntegral(sharingPhone);
                flowId = pubIntegralFlow.Id;
                // 发送奖励积分到账wx消息通知
                UserDetail userDetail = _pubUserInfoRepository.SelectDetailByPhone(sharingPhone);
                if ((userDetail.userType & 16) == 0)
                {
                    _pubMessageService.SendRewardIntegralWxMsg2User(userDetail, pubIntegralFlow.Changed_Integral, pubIntegralFlow.Create_Time);
                }
            }

            AddCouponFlow(pubCouponFlow, coupon, flowId);
            var needSmsCouponId = ",10,28,29,";
            // 如果是300元券，需要发送短信给领取人
            if (needSmsCouponId.Contains("," + coupon.Id + ","))
            {
                _pubMessageService.SendSmsCoupon300(pubCouponFlow.Receiptor_Phone);
            }
            return "";
        }

        public void AddCouponFlow(Pub_Coupon_Flow pubCouponFlow, Dic_Coupon coupon, int flowId)
        {
            // 添加优惠券流水
            pubCouponFlow.Create_Time = DateTime.Now;
            pubCouponFlow.Validity_Start_Date = DateTime.Now;

            //判断优惠券有效期限单位并计算到期时间
            int periodValidityUnit = 0;
            if (coupon.Period_Validity_Unit == 1)
            {
                periodValidityUnit = DateTime.Now.Year;
            }
            else if (coupon.Period_Validity_Unit == 2)
            {
                periodValidityUnit = DateTime.Now.Month;
            }
            else if (coupon.Period_Validity_Unit == 3)
            {
                periodValidityUnit = DateTime.Now.DayOfYear;
            }

            DateTime endDate = GetDateTime(periodValidityUnit, coupon.Period_Of_Validity);
            pubCouponFlow.Validity_End_Date = coupon.End_Validity_Date != null && endDate > coupon.End_Validity_Date ? coupon.End_Validity_Date : endDate;
            pubCouponFlow.Status = 2;
            pubCouponFlow.Integral_Flow_Id = flowId;
            //添加优惠券剩余次数
            pubCouponFlow.Times = coupon.Times_Limit;
            _pubCouponFlowRepository.InsertPubCouponFlow(pubCouponFlow);
        }

        private DateTime GetDateTime(int periodValidityUnit, int validity)
        {
            if (periodValidityUnit ==1)
            {
                return DateTime.Now.AddYears(validity);
            }
            if (periodValidityUnit == 2)
            {
                return DateTime.Now.AddMonths(validity);
            }
            if (periodValidityUnit == 3)
            {
                return DateTime.Now.AddDays(validity);
            }
            return DateTime.Now;
        }

        public Pub_Integral_Flow GainSharingIntegral(string phone)
        {
            int currentMonthIntegral = _integralFlowRepository.SelectTotalIntegralInMonth(phone);
            Pub_Integral_Flow pubIntegralFlow = new Pub_Integral_Flow();
            pubIntegralFlow.Changed_Integral = 10;
            if (currentMonthIntegral > 160)
            {
                pubIntegralFlow.Changed_Integral = 0;
                pubIntegralFlow.Remark = "积分获取已达上限";
            }
            pubIntegralFlow.Changed_Type = 1;
            pubIntegralFlow.Changed_Type_Str = "邀请好友";
            pubIntegralFlow.Status = 0;
            pubIntegralFlow.Phone_NO = phone;
            pubIntegralFlow.Create_Time = DateTime.Now;
            _integralFlowRepository.InsertPubIntegralFlow(pubIntegralFlow);

            return pubIntegralFlow;
        }

        private Dic_Coupon CanCouponReceived(int couponId, string receivePhone)
        {
            Dic_Coupon coupon = _dicCouponRepository.SelectByPrimaryKey(couponId);
            if (coupon == null || coupon.Status == 1)
            {
                return null;
            }

            if (coupon.Total_Count > 0)
            {
                // 总数量限制
                List<ReceivedCoupon> couponList = _dicCouponRepository.SelectAllReceivedCoupon();
                couponList = couponList.FindAll(p => p.CouponId == coupon.Id);
                //couponList = couponList.stream().filter(
                //        o->o.getCouponId().equals(coupon.getId())
                //).collect(Collectors.toList());
                if (couponList.Count() >= coupon.Total_Count)
                {
                    return null;
                }
            }

            if (coupon.Per_Count > 0)
            {
                // 单人限制
                List<ReceivedCoupon> couponList = _pubCouponFlowRepository.SelectReceivedCouponByPhone(receivePhone, 0);
                couponList = couponList.FindAll(p => p.ReceiptorPhone == receivePhone);
                //couponList = couponList.stream().filter(
                //        o->o.getReceiptorPhone().equals(receivePhone)
                //).filter(
                //        o->MatchUtil.isThisTime(o.getCreateTime().getTime(),
                //                Objects.requireNonNull(SinglePersonLimitedUnit.getSinglePersonLimitedUnit(coupon.getSinglePersonLimitedUnit()))
                //                        .getCode())
                //).collect(Collectors.toList());

                if (couponList.Count() >= coupon.Per_Count)
                {
                    return null;
                }
            }
            return coupon;
        }


    }
}
