using ASHermed.SinoInterface.Api.ContractModel;
using ASHermed.SinoInterface.Api.ContractModel.App;
using ASHermed.SinoInterface.Api.IRepository;
using ASHermed.SinoInterface.Api.IService;
using ASHermed.SinoInterface.Api.IService.App;
using ASHermed.SinoInterface.Api.MySqlRepository;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using ASHermed.SinoInterface.Tools;
using AngleSharp.Text;
using ASHermed.SinoInterface.Api.IRepository.Quest;
using ASHermed.SinoInterface.Api.IRepository.App;
using ASHermed.SinoInterface.Api.ContractModel.App.Entity;
using ASHermed.SinoInterface.IFramework.SMTP;
using ASHermed.SinoInterface.IFramework;
using ASHermed.SinoInterface.Api.ContractModel.SMTP;
using ASHermed.SinoInterface.Tools.Base;
using ASHermed.SinoInterface.Api.ContractModel.App.Model;
using PoJun.Util.Maps;
using Microsoft.Extensions.Logging;
using ASHermed.SinoInterface.Api.ContractModel.TCTrans.Input;
using System.IO;
using ASHermed.SinoInterface.ContractModel;
using Baidu.Aip;
using NPOI.SS.Formula.Functions;

namespace ASHermed.SinoInterface.Api.Service.App
{
    public class NewPortalService : BaseService, INewPortalService
    {
        public string aptUserCancelSmsTemplateCN = "【曜影医疗】尊敬的 [name] 女士/先生，您于[date] 在[addr]的预约已取消。如有任何疑问请致电4001862116，或客服小影微信SinoUnited9 。";
        public string aptUserCancelSmsTemplateEN = "【SinoUnited Health】Dear Mr./Ms.[name], your appointment at [date]  [addr] has been cancelled.Any question please call 4001862116 or contact customer service Ying on WeChat “SinoUnited9“.";
        private readonly ITCService _tCService;
        private readonly IHosService _hosService;
        private readonly IOutAptInfoRepository _outAptInfoRepository;
        private readonly IDicDoctorRepository _dicDoctorRepository;
        private readonly IDicDeptRepository _dicDeptRepository;
        private readonly IDicHosRepository _dicHosRepository;
        private readonly ISanFangRepository _sanFangRepository;
        private readonly IPubQuestDataRepository _pubQuestDataRepository;
        private readonly IPubPatInfoRepository _pubPatInfoRepository;
        private readonly IPubUserInfoRepository _pubUserInfoRepository;
        private readonly IPubAuthorizationRepository _pubAuthorizationRepository;
        private readonly IEmailService _emailService;
        private readonly IZhuTongSMSService _zhuTongSMSService;
        //private readonly IRabbitMQService _rabbitMQService;
        private readonly AppConfigurtaion _appConfigurtaion;
        private readonly IBaiduService _baiduService;
        private readonly IFileService _fileService;
        private readonly IPubMapUserPatRepository _pubMapUserPatRepository;
        private readonly ILogger<NewPortalService> _logger;
        private readonly IFileRepository _fileRepository;
        private readonly IOrderService _orderService;

        public NewPortalService(ITCService tCService, IHosService hosService, IOutAptInfoRepository outAptInfoRepository, IDicDoctorRepository dicDoctorRepository, IDicDeptRepository dicDeptRepository, IDicHosRepository dicHosRepository, ISanFangRepository sanFangRepository, IPubQuestDataRepository pubQuestDataRepository, IPubPatInfoRepository pubPatInfoRepository, IPubUserInfoRepository pubUserInfoRepository, IPubAuthorizationRepository pubAuthorizationRepository, IEmailService emailService, IZhuTongSMSService zhuTongSMSService, AppConfigurtaion appConfigurtaion, IBaiduService baiduService, IFileService fileService, IPubMapUserPatRepository pubMapUserPatRepository, ILogger<NewPortalService> logger, IFileRepository fileRepository, IOrderService orderService)
        {
            _tCService = tCService;
            _hosService = hosService;
            _dicDoctorRepository = dicDoctorRepository;
            _dicDeptRepository = dicDeptRepository;
            _outAptInfoRepository = outAptInfoRepository;
            _dicHosRepository = dicHosRepository;
            _sanFangRepository = sanFangRepository;
            _pubQuestDataRepository = pubQuestDataRepository;
            _pubPatInfoRepository = pubPatInfoRepository;
            _pubAuthorizationRepository = pubAuthorizationRepository;
            _emailService = emailService;
            _zhuTongSMSService = zhuTongSMSService;
            //_rabbitMQService = rabbitMQService;
            _pubUserInfoRepository = pubUserInfoRepository;
            _appConfigurtaion = appConfigurtaion;
            _baiduService = baiduService;
            _fileService = fileService;
            _pubMapUserPatRepository = pubMapUserPatRepository;
            _logger = logger;
            _fileRepository = fileRepository;
            _orderService = orderService;
        }

        /// <summary>
        /// 获取医生详情
        /// </summary>
        /// <param name="docId"></param>
        /// <returns></returns>
        public Dic_Doctor GetDoctorDetail(int docId, int language)
        {
            return _dicDoctorRepository.SelectById(docId, language);
        }

        /// <summary>
        /// 获取科室详情
        /// </summary>
        /// <param name="deptId"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public DeptModel GetDeptDetail(int deptId, int language)
        {
            return _dicDeptRepository.GetDeptById(deptId, language);
        }

        /// <summary>
        /// 科室预约
        /// </summary>
        /// <param name="language"></param>
        /// <param name="lon"></param>
        /// <param name="lat"></param>
        /// <param name="deptId"></param>
        /// <param name="taday"></param>
        /// <param name="hosId"></param>
        /// <returns></returns>
        public List<NewPortalSlotDateForDeptModel> GetSchedulingForDept(int language, double lon, double lat, int deptId, string today, int hosId = 0, bool isShowAll = false)
        {
            //var s = _tCService.GetCPWithSlotsForDate("2021-11-26", "2021-11-26", "84", "312");
            List<NewPortalSlotDateForDeptModel> response = new List<NewPortalSlotDateForDeptModel>();
            List<HosByLanguage> hoslist = new List<HosByLanguage>();
            var hos = _hosService.GetForDept(deptId);
            if (isShowAll)
            {
                var allhos = _hosService.SelectListByLanguage(language, lon, lat);
                foreach (var item in allhos.OrderBy(o => o.DistanceDouble))
                {
                    if (hos.Where(w => w.Apt_Hos_Id == item.Id).Any())
                        hoslist.Add(item);
                }
            }
            else
            {
                hoslist.Add(_dicHosRepository.SelectById(hosId, language));
                //var allhos = _hosService.SelectListByLanguage(language, lon, lat);
                //foreach (var item in hos)
                //{
                //    if (allhos.Where(w => w.Id == item.Apt_Hos_Id).Any())
                //    {
                //        hoslist.Add(allhos.Where(w => w.Id == item.Apt_Hos_Id).FirstOrDefault());
                //    }
                //}
            }

            foreach (var itemhos in hoslist)
            {
                var deptserv = _outAptInfoRepository.SelectDeptServDoctor(itemhos.Id, deptId, language);
                response.Add(SlotDateDetail(deptserv, deptId, today, itemhos, language));
            }

            foreach (var item in response)
            {
                var doc = _dicDoctorRepository.GetDocForHisDocId(new List<string>(), deptId, item.HosId);
                foreach (var itemdoc in doc)
                {
                    if (!item.Doctor.Where(w => w.DocId == itemdoc.Id).Any())
                    {
                        if (itemdoc.APT_Type == 2 || itemdoc.APT_Type == 4)
                        {
                            if (language == 1)
                                item.Doctor.Add(new SlotDateForDoctor { DocId = itemdoc.Id, DocName = itemdoc.CN_Name, ImgList = itemdoc.List_Image, DocLanguage = itemdoc.CN_Language });
                            else
                                item.Doctor.Add(new SlotDateForDoctor { DocId = itemdoc.Id, DocName = itemdoc.EN_Name, ImgList = itemdoc.List_Image, DocLanguage = itemdoc.EN_Language });
                        }
                    }
                }
            }
            //没有排班显示电话预约
            foreach (var item in response)
            {
                foreach (var item2 in item.Doctor)
                {
                    var isPhoneReservation = true;
                    item2.Service.ForEach(w => { if (w.AptSlotList.Count > 0) { isPhoneReservation = false; } });
                    item2.IsPhoneReservation = isPhoneReservation;
                }
            }

            //当天18点后没有可预约的排班，科室/医生选择日期页面，不需要显示诊所医生，直接显示空页面
            if (DateTime.Now > DateTime.Parse(today + " 18:00:01"))
            {
                if (!response.Where(w => w.Doctor.Where(e => !e.IsPhoneReservation).Any()).Any())
                {
                    response = new List<NewPortalSlotDateForDeptModel>();
                }
            }

            return response;

        }

        public NewPortalDeptDetail GetNewPortalDeptDetail(int deptId, int language)
        {
            NewPortalDeptDetail response = new NewPortalDeptDetail();
            var dept = _dicDeptRepository.GetDeptById(deptId, language);
            response.Id = dept.Id;
            response.DeptName = dept.DeptName;
            response.DeptImg = dept.Icon;
            response.DeptDesc = dept.Desc;
            return response;
        }

        public NewPortalSlotDateForDeptModel SlotDateDetail(List<SchedulingParam> deptserv, int deptId, string taday, HosByLanguage hos, int language)
        {
            var dept = _dicDeptRepository.GetDeptById(deptId, language);
            NewPortalSlotDateForDeptModel res = new NewPortalSlotDateForDeptModel();
            res.HosId = hos.Id;
            res.HosName = hos.Name;
            res.Longitude = hos.Longitude;
            res.Latitude = hos.Latitude;
            res.Addr = hos.Addr;
            res.DeptId = dept.Id;
            res.DeptName = dept.DeptName;
            res.Distance = hos.Distance;

            foreach (var itemdeptserv in deptserv)
            {
                var tcslote = _tCService.GetCPWithSlotsForDate(taday, taday, itemdeptserv.His_Dept_Id.ToString(), itemdeptserv.His_Serv_Id).ChangeModel();
                if (tcslote != null && tcslote.SlotDates.Any())
                {
                    var doc = _dicDoctorRepository.GetDocForHisDocIds(tcslote.SlotDates.FirstOrDefault().Resources.Select(f => f.CareProvID).ToList(), deptId, language, hos.Id);
                    foreach (var itemdoc in tcslote.SlotDates.FirstOrDefault().Resources)
                    {
                        var docitem = doc.Where(w => w.CareProvID == itemdoc.CareProvID).FirstOrDefault();
                        if (docitem == null)
                        {
                            continue;
                        }
                        SlotDateForDoctor docter = new SlotDateForDoctor();
                        List<SlotDateForService> services = new List<SlotDateForService>();
                        SlotDateForService service = new SlotDateForService();
                        service.ServiceCode = itemdeptserv.His_Serv_Id;
                        service.ServName = itemdeptserv.CnServName;
                        service.AptProj = itemdeptserv.ServiceId;

                        docter.DocId = docitem.Id;
                        docter.DocName = docitem.CN_Name;
                        docter.ImgList = docitem.List_Image;
                        docter.DocLanguage = docitem.CN_Language;
                        if (docitem.APT_Type == 4)
                        {
                            foreach (var item in itemdoc.Slots)
                            {
                                if (DateTime.Now.AddHours(1) > DateTime.Parse(taday + " " + item.StartTime))
                                {
                                    continue;
                                }
                                service.AptSlotList.Add(new NewPortalSlotDateForDept { StartTime = DateTime.Parse(DateTime.Now.Date.ToString("yyyy-MM-dd") + " " + item.StartTime).ToString("HH:mm"), DateType = item.IsAfternoonSpecified ? 1 : 0, AptUsrn = item.USRN });
                            }
                        }
                        services.Add(service);
                        docter.Service = services;
                        docter.IsPhoneReservation = false;

                        var serv = res.Doctor.Where(w => w.DocId == docter.DocId).FirstOrDefault();
                        if (serv != null)
                        {
                            serv.Service.AddRange(docter.Service);
                        }
                        else
                        {
                            res.Doctor.Add(docter);
                        }
                    }
                }
            }
            return res;

        }

        public async Task<AptDocInfo> GetAptDocInfo(int docId, int language)
        {
            return await _dicDoctorRepository.GetAptDocInfo(docId, language);
        }

        public async Task<AptDocScheduling> GetDocScheduling(int docId, int deptId, string dateTime, double lon, double lat, int language)
        {
            AptDocScheduling docScheduling = new AptDocScheduling();
            var docDept = await _dicDoctorRepository.GetDocDepts(docId, deptId, language);
            if (docDept?.Count > 0)
            {
                AptHos hos = null;
                var hosList = docDept.OrderBy(p => p.SORT).Select(p => p.APT_HOS_ID).ToList().Distinct();
                foreach (var hosId in hosList)
                {
                    hos = new AptHos();
                    var hosServs = docDept.FindAll(p => p.APT_HOS_ID == hosId);
                    hos.DeptName = hosServs.FirstOrDefault().DeptName;
                    var pics = hosServs.FirstOrDefault().PICTURE;
                    if (!string.IsNullOrEmpty(pics) && pics.Contains(","))
                    {
                        hos.HosPic = pics.Substring(0, pics.IndexOf(','));
                    }
                    hos.HosId = hosServs.FirstOrDefault().APT_HOS_ID;
                    hos.DeptId = hosServs.FirstOrDefault().APT_DEPT_ID;
                    hos.DocId = hosServs.FirstOrDefault().APT_DOCTOR_ID;
                    hos.HosName = hosServs.FirstOrDefault().HosName;
                    if (lon > 0 && lat > 0)
                    {
                        hos.Distence = Common.GetDistance(lat, lon, hosServs.FirstOrDefault().LATITUDE.ToDouble(), hosServs.FirstOrDefault().LONGITUDE.ToDouble());
                    }
                    //aptHos.IsServiceApt = item.APT_TYPE == 2 ? true : false;
                    if (hosServs.FirstOrDefault().APT_TYPE == 4)
                    {
                        hos.IsServiceApt = true;
                        hos.ServSlotList = new List<ServSlot>();
                        ServSlot servSlot = null;
                        foreach (var item in hosServs)
                        {
                            servSlot = new ServSlot();
                            servSlot.AptSlotList = _tCService.GetAptScheduling(dateTime, dateTime, item.HIS_DEPT_ID + "", item.HIS_SERV_ID + "", item.CARE_PROV_ID + "");
                            servSlot.ServName = item.ServName;
                            servSlot.AptProj = item.AptProj;
                            servSlot.Day = dateTime;
                            if (servSlot.AptSlotList?.Count > 0)
                            {
                                hos.IsServiceApt = false;
                                hos.ServSlotList.Add(servSlot);
                            }

                        }
                    }
                    else if (hosServs.FirstOrDefault().APT_TYPE == 2)
                    {
                        hos.IsServiceApt = true;
                        hos.ServSlotList = new List<ServSlot>();
                    }
                    docScheduling.HosList.Add(hos);
                }
            }
            if (lon > 0 && lat > 0)
            {
                docScheduling.HosList = docScheduling.HosList.OrderBy(p => p.Distence).ToList();
            }

            //当天18点后没有可预约的排班，科室/医生选择日期页面，不需要显示诊所医生，直接显示空页面
            if (DateTime.Now > DateTime.Parse(dateTime + " 18:00:01"))
            {
                foreach (var item in docScheduling.HosList)
                {
                    if (item.ServSlotList.Count() <= 0)
                    {
                        item.IsDelete = true;
                    }
                }
            }
            docScheduling.HosList = docScheduling.HosList.Where(w => !w.IsDelete).ToList();

            return docScheduling;
        }

        public async Task<AptRecordModel> GetUserLockRecord()
        {
            try
            {
                var user = GetBaseUserInfo();
                var lockInfo = await _sanFangRepository.GetLockRecord(user.ID);
                if (lockInfo?.Record != null)
                {
                    var model = JsonConvert.DeserializeObject<AptRecordModel>(lockInfo.Record);
                    var hour = model.AptTime.Value.Hour;
                    var type = 0;
                    if (hour >= 12)
                    {
                        type = 1;
                    }
                    model.DateType = type;
                    var pat = _pubPatInfoRepository.SelectById(model.PatId);
                    model.PatName = pat.Pat_Name;
                    model.PatMrn = pat.Pat_MRN;
                    return model;
                }
                return null;
            }
            catch (System.Exception)
            {
                return null;
            }
        }

        public async Task<bool> UserAbandonApt()
        {
            var user = GetBaseUserInfo();
            var hasApt = _sanFangRepository.GetAbandonApt(user.ID);
            foreach (var item in hasApt)
            {
                _tCService.LockApt(item.AptUsrn, item.AptUsrn, "U");
            }
            return await _sanFangRepository.UserAbandonApt(user.ID);
        }

        public async Task<AptDetail> GetOutAptInfoDetail(int aptId, int wechatStatus, int language)
        {
            var info = await _outAptInfoRepository.GetOutAptInfoDetail(aptId, language);
            if (info == null)
            {
                return new AptDetail();
            }
            var hour = info.Apt_Time.Hour;
            var lab = "AM";
            if (hour >= 12)
            {
                lab = "PM";
            }
            info.AptDay = info.Apt_Time.ToString("MM-dd");
            info.AptTime = info.Apt_Time.ToString("hh:mm") + lab;
            var week = (int)info.Apt_Time.DayOfWeek;
            info.WeekDay = Common.GetWeekDay(week, language);
            //获取详情页 是否是当天  是:需要显示问卷  改为一直显示
            info.IsNeedQuest = true;
            info.InfoId = 3;//写死 流调问卷
            //if (DateTime.Now.ToString("yyyy-MM-dd") == info.Apt_Time.ToString("yyyy-MM-dd"))
            //{
            //    var questData = _pubQuestDataRepository.GetCurDayQuestData(info.PatId, info.InfoId);
            //    if (questData?.Count > 0)
            //    {
            //        info.IsAnswer = true;
            //        info.IsPass = questData.FirstOrDefault().IsPass;
            //        info.QuestTime = questData.FirstOrDefault().CreateTime;
            //    }
            //}
            //else 
            if (Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")) <= Convert.ToDateTime(info.Apt_Time.ToString("yyyy-MM-dd")))
            {
                var questData = _pubQuestDataRepository.GetAptDayQuestData(info.PatId, info.InfoId, info.AptCreateTime.ToString("yyyy-MM-dd"));
                if (DateTime.Now.ToString("yyyy-MM-dd") == info.Apt_Time.ToString("yyyy-MM-dd"))
                {
                    if (questData != null && questData.CreateTime.ToString("yyyy-MM-dd") == info.Apt_Time.ToString("yyyy-MM-dd"))
                    {
                        info.IsAnswer = true;
                        info.IsPass = questData.IsPass;
                        info.QuestTime = questData.CreateTime;
                    }
                }
                else if (Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")) < Convert.ToDateTime(info.Apt_Time.ToString("yyyy-MM-dd")))
                {
                    if (questData != null)
                    {
                        info.IsAnswer = true;
                        info.IsPass = questData.IsPass;
                        info.QuestTime = questData.CreateTime;
                    }
                }
            }
            else
            {
                info.IsNeedQuest = false;
            }
            var patInfo = _pubPatInfoRepository.SelectById(info.PatId);
            if (!string.IsNullOrEmpty(patInfo.EmergencyPhone) && patInfo.ContactWay > 0)
            {
                info.IsPerf = true;
            }
            info.WechatStatus = wechatStatus;
            //0线下预约 1流感疫苗 2健康评估
            if (wechatStatus == 1)
            {
                var vaccApt = _outAptInfoRepository.GetVaccAptInfo(aptId, language);
                if (vaccApt != null)
                {
                    info.VaccineBrand = vaccApt.VaccineBrand;
                    info.VaccineName = vaccApt.VaccineName;
                }
                else
                {
                    info.VaccineName = language == 1 ? "流感疫苗" : "Flu Shot";
                }
            }
            if (wechatStatus == 2)
            {
                info.PhysicalName = "健康评估";
                var apt = _outAptInfoRepository.GetOutAptInfo(aptId);
                var quests = _pubQuestDataRepository.GetPatQuest(info.PatId);
                if (apt != null)
                {
                    var quest = quests.FindAll(p => p.PatId == info.PatId && p.AptId == apt.Id);
                    if (quest?.Count > 0)
                    {
                        info.PhysicalId = quest.FirstOrDefault().InfoId;
                    }
                    else
                    {
                        info.PhysicalId = 0;
                    }
                }
            }
            if ((info.InnerStatus == 1 || info.InnerStatus == 4) && info.Apt_Time < Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")))
            {
                info.Status = 5;
            }
            if (info.InnerStatus == 8 || info.InnerStatus == 16 || info.InnerStatus == 32)
            {
                info.Status = 5;
            }
            if (info.InnerStatus == 2 && info.Status == 4)
            {
                info.Status = info.InnerStatus;
            }
            return info;
        }

        public async Task<BaseResponse<int>> AgainApt(int aptId)
        {
            BaseResponse<int> response = new BaseResponse<int>();
            var info = await _outAptInfoRepository.GetOutAptInfoDetail(aptId, 1);
            var doc = _dicDoctorRepository.SelectById(info.DocId, 1);
            var dept = _dicDeptRepository.SelectByIdLanguage(1, info.DeptId);
            var deptserv = _outAptInfoRepository.SelectDeptServDoctor(info.HosId, info.DeptId, 1);
            if (doc == null || info.DocId == 0 || doc.Is_Deleted || doc.APT_Type == 1)
            {
                response.Data = 1;
            }
            if (dept == null || info.DeptId == 0 || info.HosId == 0 || !deptserv.Any())
            {
                response.Data = 2;
            }
            if (info.DocId == 0 && info.DeptId == 0 && info.HosId == 0)
            {
                response.Data = 3;
            }
            response.Code = 1;
            response.Msg = "成功";
            return response;
        }

        public bool CheckQuest(AptCommitModel model)
        {
            var questData = _pubQuestDataRepository.GetCurDayQuestData(model.PatId, 3);
            if (questData?.Count > 0)
            {
                return true;
            }
            return false;
        }

        public async Task<int> UserFeedback(UserFeedback feedback)
        {
            var ent = new User_Feedback();
            ent.Content = feedback.Content;
            ent.ContactWay = feedback.ContactWay;
            ent.CreateTime = DateTime.Now;
            ent.UserId = GetBaseUserInfo()?.ID;
            return await _sanFangRepository.InsertUserFeedback(ent);
        }

        /// <summary>
        /// 获取授权申请内容
        /// </summary>
        /// <returns></returns>
        public List<Pub_Authorization_Detail> GetAuthorizationDetail(int language)
        {
            var data = _pubAuthorizationRepository.GetAuthorizationDetail();
            foreach (var item in data)
            {
                if (language != 1)
                {
                    item.Name = item.NameEN;
                    item.Remark = item.RemarkEN;
                    item.PdfContent = item.PdfContentEN;
                }
            }
            return data;
        }
        /// <summary>
        /// 创建授权申请
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool CreateAuthorization(Pub_AuthorizationDto model, int language)
        {
            if (model.IsForever)
            {
                model.AuthorizationValidity = DateTime.MinValue;
            }
            var pat = _pubPatInfoRepository.SelectById(model.PatId);
            var user = GetBaseUserInfo();

            //var userpat = _pubAuthorizationRepository.GetAuthorizationUserPat(model.PatId).Where(w => w.AuthorizationValidity > DateTime.Now).Select(s => s.UserId).ToList();
            //userpat.Add(user.ID);
            //if (userpat.GroupBy(g => g).Count() > 2)
            //{
            //    return false;
            //}

            var upauth = _pubAuthorizationRepository.GetUserAuthorizationByPatStatus(user.ID, model.PatId);
            if (upauth.AuthorizationMethod.Split(',').Length > 1)
            {
                return false;
            }
            if (model.AuthorizationMethod.Split(',').Length > 1)
            {
                return false;
            }
            if (upauth.AuthorizationMethod == model.AuthorizationMethod)
            {
                return false;
            }
            else
            {
                if (upauth.CreateTime.AddMinutes(5) > DateTime.Now)
                {
                    return false;
                }
            }

            //创建新授权的时候，失效掉以前的所有授权中，已授权的授权数据
            _pubAuthorizationRepository.InvalidAuthorization(user.ID, model.PatId);

            model.CreateTime = DateTime.Now;
            model.IsDelete = false;
            model.Status = 1;
            model.UserId = user.ID;
            model.AuthorizationValidity = model.AuthorizationValidity.Date.AddHours(23).AddMinutes(59).AddSeconds(59);
            var res = _pubAuthorizationRepository.InsertAuthorization(model);
            model.Id = res;
            if (res > 0)
            {
                var url = _appConfigurtaion.GetSionViewDomain + "AuthorizationReview?id=" + res;
                url = _baiduService.GetShortUrl(url);
                foreach (var item in model.AuthorizationMethod.Split(','))
                {
                    //邮件
                    if (item == "1")
                    {
                        var emailSendInput = new EmailSendInput();
                        if (language == 1)
                        {
                            //TODO 换链接
                            emailSendInput = new EmailSendInput
                            {
                                To = new List<string>
                            {
                                pat.Email
                            },
                                Subject = "【曜影医疗】授权申请",
                                TextBody = "【曜影医疗】" + pat.Pat_Name + "，您好！(" + user.Nick_Name + "/" + user.Phone + ")已将您绑定为曜影医疗APP/小程序的家庭成员，现向您申请授权，点击链接 #" + url + "#签名授权，链接半小时内有效(系统邮件请勿回复)",
                            };
                        }
                        else
                        {
                            emailSendInput = new EmailSendInput
                            {
                                To = new List<string>
                            {
                                pat.Email
                            },
                                Subject = "【SinoUnited Health】Authorization Application",
                                TextBody = "【SinoUnited Health】Dear " + pat.Pat_Name + ", (" + user.Nick_Name + "/" + user.Phone + ") has linked you as a family member and applied for authorization on SinoUnited Health APP/ Mini Program. Please open #" + url + "# to manage authorization. This link valid for 30mins. System email. DO NOT REPLY",
                            };
                        }
                        _emailService.Send(emailSendInput);
                    }
                    //短信
                    else if (item == "2")
                    {
                        var content = "";
                        if (language == 1)
                        {
                            content = "【曜影医疗】" + pat.Pat_Name + "，您好！(" + user.Nick_Name + "/" + user.Phone + ")已将您绑定为曜影医疗APP/小程序的家庭成员，现向您申请授权，点击链接 " + url + " 签名授权，链接半小时内有效(系统信息，请勿回复)";
                        }
                        else
                        {
                            content = "【SinoUnited Health】Dear " + pat.Pat_Name + ", (" + user.Nick_Name + "/" + user.Phone + ") has linked you as a family member and applied for authorization on SinoUnited Health APP/ Mini Program. Please open " + url + " to manage authorization. This link valid for 30mins. DO NOT REPLY this message";
                        }
                        _zhuTongSMSService.SendSMS(pat.Phone_NO, content);
                    }
                }

                //var pushmodel = new RabbitMsgModel<string> { Key = RabbitMQQueue.PubAuthorization, Data = model.ToJson() };
                //推送延时队列，30分钟后修改状态为授权超时
                //_rabbitMQService.Publish<string>(pushmodel, 30 * 60 * 1000, 30 * 1000);

                return true;
            }
            return false;
        }
        /// <summary>
        /// 获取用户最新提交的授权申请不按照授权时间，因为这个接口只拉取最新的授权，给用户查看
        /// </summary>
        /// <returns></returns>
        public Pub_AuthorizationDto GetAuthorization(int patId)
        {
            var res = _pubAuthorizationRepository.GetAuthorization(GetBaseUserInfo().ID, patId);
            if (res != null)
            {
                if (res.Status == 3)
                {
                    res.ApplyDetailIds = res.ExamineDetailIds;
                }

                res.Status = res.Status != 1 && !res.IsForever && res.AuthorizationValidity < DateTime.Now && res.AuthorizationTime != DateTime.MinValue ? 5 : res.Status;
            }
            return res;
        }
        /// <summary>
        /// 通过授权ID获取授权详情，给邮件短信链接获取授权详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public PubAuthorizationView GetAuthorizationForId(int id)
        {
            var res = _pubAuthorizationRepository.GetAllAuthorizationForId(id);
            if (res != null)
            {
                var result = JsonConvert.DeserializeObject<PubAuthorizationView>(res.ToJson());
                result.UserInfo = _pubUserInfoRepository.SelectById(res.UserId);
                result.PatInfo = _pubPatInfoRepository.SelectById(res.PatId);
                if (result.Status == 3)
                {
                    result.ApplyDetailIds = result.ExamineDetailIds;
                }
                return result;
            }
            return new PubAuthorizationView();
        }

        /// <summary>
        /// 患者授权接口，给邮件短信链接授权
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public BaseResponse<bool> Authorization(Pub_AuthorizationDto model)
        {
            BaseResponse<bool> response = new BaseResponse<bool>();

            var authdetail = _pubAuthorizationRepository.GetAuthorizationForId(model.Id);

            if ((DateTime.Now - authdetail.CreateTime).TotalMilliseconds > 60 * 30 * 1000)
            {
                model.AuthorizationValidity = model.AuthorizationValidity.Date.AddHours(23).AddMinutes(59).AddSeconds(59);
                model.AuthorizationTime = DateTime.Now;
                model.ExamineDetailIds = model.ApplyDetailIds;
                model.Status = 2;
                model = _fileService.GetFileContentAdd<Pub_AuthorizationDto>(model);
                _pubAuthorizationRepository.UpdateAuthorization(model.Id, model.Status, model.AuthorizationTime, model.ExamineDetailIds, model.AuthorizationValidity, model.IsForever, model.AuthorizationPdf, model.AuthorizationImg);

                response.Code = 0;
                response.Msg = "此授权申请超过有效时间半小时，请重新授权";
                response.Data = false;
                return response;
            }

            var userpat = _pubAuthorizationRepository.GetAuthorizationUserPat(authdetail.PatId).Where(w => (w.AuthorizationValidity > DateTime.Now || w.IsForever) && w.Status == 3).Select(s => s.UserId).ToList();
            if (userpat.GroupBy(g => g).Count() >= 2)
            {
                response.Code = 0;
                response.Msg = "您最多只能同时授权两个用户";
                response.Data = false;
                return response;
            }

            model.AuthorizationValidity = model.AuthorizationValidity.Date.AddHours(23).AddMinutes(59).AddSeconds(59);
            var file = _fileRepository.GetFilesContentForId(int.Parse(model.AuthorizationPdf));
            model.AuthorizationTime = DateTime.Now;
            model.ExamineDetailIds = model.ApplyDetailIds;
            model.Status = 3;
            model = _fileService.GetFileContentAdd<Pub_AuthorizationDto>(model);
            var auth = _pubAuthorizationRepository.GetAuthorizationForId(model.Id);
            var res = _pubAuthorizationRepository.UpdateAuthorization(model.Id, model.Status, model.AuthorizationTime, model.ExamineDetailIds, model.AuthorizationValidity, model.IsForever, model.AuthorizationPdf, model.AuthorizationImg);
            if (res > 0)
            {
                if (file != null)
                {
                    var user = _pubUserInfoRepository.SelectByPrimaryKey(auth.UserId);
                    var pat = _pubPatInfoRepository.SelectById(auth.PatId);
                    if (user != null)
                    {
                        //var picParRef = _tCService.GetEpisodesForPatient(pat.Pat_MRN);
                        //if (picParRef.Any())
                        //{
                        //    var tcres = _tCService.CustomCRMMRPictures(picParRef.FirstOrDefault().PAADMMainMRADMDR, "授权协议", pat.Pat_Name + "(" + pat.Mrn + ")-" + DateTime.Now.ToString("yyyyMMdd") + "-" + ((auth.Source == 1) ? "小程序" : ((auth.Source == 2) ? "IOS" : "安卓")), file.Content, "Patient Document");
                        //    _logger.LogInformation("Authorization:" + file.Id + "   reb:" + tcres);
                        //}

                        var fileName = file.FileUrl.Split('\\')?.LastOrDefault();
                        var crmPicturesResponse = _tCService.CustomCRMPictures(pat.Pat_ID, user.Nick_Name + "-" + DateTime.Now.ToString("yyyyMMdd") + "-" + ((auth.Source == 1) ? "小程序" : ((auth.Source == 2) ? "IOS" : "安卓")), fileName, file.Content);

                        _logger.LogInformation("SendAuthorizationFileToTc:" + file.Id + "   reb:" + crmPicturesResponse);
                    }
                }

                //授权成功备注推tc
                AuthorizationPullTcRemark(model.Id);

                response.Code = 1;
                response.Msg = "成功";
                response.Data = true;
                return response;
            }
            response.Code = 0;
            response.Msg = "授权失败";
            response.Data = false;
            return response;
        }

        public BaseResponse<bool> CheckAuthorization(int patid, bool isAdd, int language)
        {
            BaseResponse<bool> response = new BaseResponse<bool>();
            var userpat = _pubAuthorizationRepository.GetAuthorizationUserPat(patid).Where(w => (w.AuthorizationValidity > DateTime.Now || w.IsForever) && w.Status == 3).Select(s => s.UserId).ToList();
            //if (isAdd)
            //{
            //    userpat.Add(GetBaseUserInfo().ID);
            //}
            if (userpat.GroupBy(g => g).Count() >= 2)
            {
                response.Code = 0;
                if (language == 1)
                    response.Msg = "您最多只能同时授权两个用户";
                else
                    response.Msg = "You can only authorize up to two users at the same time";
                response.Data = false;
                return response;
            }
            response.Code = 1;
            response.Msg = "成功";
            response.Data = true;
            return response;
        }

        /// <summary>
        /// 授权成功备注推tc
        /// </summary>
        /// <param name="authorizationId"></param>
        private void AuthorizationPullTcRemark(int authorizationId)
        {
            Task.Run(async () =>
            {
                var authorization = _pubAuthorizationRepository.GetAuthorizationForId(authorizationId);

                if (authorization == null)
                {
                    return;
                }

                var patient = _pubPatInfoRepository.SelectById(authorization.PatId);
                var user = _pubUserInfoRepository.SelectByPrimaryKey(authorization.UserId);

                var authIds = authorization.ExamineDetailIds.Split(',');

                if (patient == null || user == null || !authIds.Any())
                {
                    return;
                }

                var tcRowId = int.TryParse(patient.Pat_ID, out var rowId) ? rowId : default;

                var tcPatInfoByRowId = _tCService.PAPersonEditOpen(tcRowId);
                if (tcPatInfoByRowId != null)
                {
                    var tcPatientByPId = (await _tCService.GetPatientAsync(new GetPatientInput
                    {
                        MRN = patient.Pat_MRN
                    })).Persons.FirstOrDefault();

                    //var howknows = await _pubUserInfoRepository.GetHowknow();
                    //var howknow = howknows.FirstOrDefault(w => w.TcShow.ToLower() == tcPatInfoByRowId?.ASSISDesc?.ToLower());

                    var updateTcInput = new CustomCRMPAPerson
                    {
                        PAPERCityCodeDR = "上海市",//小P让改的
                        PAPERStName = tcPatInfoByRowId.PAPERStName,
                        PAPERDob = tcPatInfoByRowId.PAPERDob,
                        PAPEREmail = tcPatInfoByRowId.PAPEREmail,
                        PAPERHowDidYouLearnUsDR = tcPatInfoByRowId?.ASSISDesc,
                        PAPERID = tcPatientByPId?.PAPERID,
                        PAPERMobPhone = tcPatInfoByRowId?.PAPERMobPhone,
                        PAPERName = tcPatInfoByRowId.PAPERName,
                        PAPERName2 = tcPatInfoByRowId.PAPERName2,
                        //PAPERName3 = tcPatientByPId?.PAPERName3,
                        PAPERNationDR = tcPatientByPId?.PAPERNation,
                        PAPERNokCTRLTDR = tcPatInfoByRowId.PAPERNokName,
                        PAPERNokName = tcPatInfoByRowId.PAPERNokName,
                        PAPERNokPhone = tcPatInfoByRowId.PAPERNokPhone,
                        PAPERPreferredContactMethod = tcPatInfoByRowId.PAPERPreferredContactMethod,
                        PAPERRowId = tcRowId,
                        PAPERSexDR = tcPatInfoByRowId.CTSEXDesc.Contains("男") ? "M" : "F",
                        PAPERRemark = new List<PAPERRemark>()
                    };

                    if (!string.IsNullOrEmpty(tcPatInfoByRowId?.PAPERRemark))
                    {
                        var arr = tcPatInfoByRowId.PAPERRemark.Split(new[] { "\r\n" }, StringSplitOptions.None);
                        foreach (var item in arr)
                        {
                            updateTcInput.PAPERRemark.Add(new PAPERRemark { PAPERRemarkItem = item });
                        }
                    }

                    var remarkStringBuilder = new StringBuilder();
                    remarkStringBuilder.Append($"授权{user.Nick_Name}（{user.Phone}） ");

                    var authInfo = authIds.Select(x =>
                        {
                            switch (x)
                            {
                                case "1":
                                    return "预约就诊";
                                case "2":
                                    return "互联网医院预约";
                                case "3":
                                    return "查看报告";
                                case "4":
                                    return "互联网医院账单";
                                default:
                                    return "";
                            }
                        })
                        .Aggregate((prev, current) => prev + "、" + current);

                    remarkStringBuilder.Append($"{authInfo}，");
                    remarkStringBuilder.Append(authorization.IsForever ? "有效期至永久" : $"有效期至 {authorization.AuthorizationValidity:yyyy-MM-dd}");

                    updateTcInput.PAPERRemark.Add(new PAPERRemark
                    {
                        PAPERRemarkItem = remarkStringBuilder.ToString()
                    });

                    var updateTcResult = _tCService.CustomCRMPAPerson(updateTcInput);

                    if (!updateTcResult)
                    {
                        _logger.LogInformation($"授权成功后，给TC患者传备注失败：param-({authorizationId}),pullTcParam-{updateTcInput.ToJson()}");
                    }
                }
            });
        }

        public bool NoAuthorization(int id)
        {
            var res = _pubAuthorizationRepository.UpdateAuthorizationStatus(id, 4);
            if (res > 0)
            {
                return true;
            }
            return false;
        }

        public List<PubAuthorizationView> AuthorizationList()
        {
            var user = GetBaseUserInfo();
            List<PubAuthorizationView> result = new List<PubAuthorizationView>();
            var oneself = _pubMapUserPatRepository.GetByUserIdOneself(user.ID);
            if (oneself == null)
            {
                return result;
            }
            var data = _pubAuthorizationRepository.GetPubAuthorizationList(oneself.Pat_ID);
            var userIdList = data.Select(w => w.UserId).Distinct().ToList();
            List<Pub_AuthorizationDto> dateTo = new List<Pub_AuthorizationDto>();
            foreach (var item in userIdList)
            {
                var time = data.Max(p => p.AuthorizationTime);
                dateTo.Add(data.Find(p => p.UserId == item && p.AuthorizationTime == time));
            }
            var pats = _pubPatInfoRepository.SelectById(oneself.Pat_ID);
            var users = _pubUserInfoRepository.SelectByIds(data.Select(w => w.UserId).ToList());
            result = dateTo.MapTo<List<PubAuthorizationView>>();
            foreach (var item in result)
            {
                item.PatInfo = pats;
                item.MyUserInfo = user;
                item.UserInfo = users.Where(w => w.ID == item.UserId).FirstOrDefault();
                if (item.Status != 1 && item.AuthorizationValidity < DateTime.Now && item.AuthorizationTime != DateTime.MinValue)
                {
                    item.Status = 5;
                }
            }
            return result;
        }

        public List<PubAuthorizationView> BindList()
        {
            var myUserInfo = GetBaseUserInfo();
            List<PubAuthorizationView> result = new List<PubAuthorizationView>();
            var oneself = _pubMapUserPatRepository.GetByUserIdOneself(myUserInfo.ID);
            if (oneself == null)
            {
                return result;
            }
            var pat = _pubPatInfoRepository.SelectById(oneself.Pat_ID);
            var mapdata = _pubMapUserPatRepository.GetBind(oneself.Pat_ID).Where(w => w.Relation_Ship == 1 || w.Relation_Ship == 2).ToList();
            var map = mapdata.GroupBy(g => g.User_ID);
            var users = _pubUserInfoRepository.SelectByIds(map.Select(w => w.Key).ToList());
            var auths = _pubAuthorizationRepository.GetUserAuthorizationsByPats(map.Select(w => w.Key).ToList(), oneself.Pat_ID);
            foreach (var item in map)
            {
                var mapdetail = mapdata.Where(w => w.User_ID == item.Key)?.FirstOrDefault();

                if (mapdetail == null)
                {
                    continue;
                }

                var itemUserInfo = users.Where(w => w.ID == item.Key)?.FirstOrDefault();

                if (itemUserInfo == null || myUserInfo.ID == itemUserInfo?.ID)
                {
                    continue;
                }

                var auth = auths.FirstOrDefault(w => w.UserId == item.Key);
                if (auth != null && auth.Status != 1 && !auth.IsForever && auth.AuthorizationValidity < DateTime.Now && auth.AuthorizationTime != DateTime.MinValue)
                {
                    auth.Status = 5;
                }

                //又是为了兼容老数据……
                if (mapdetail.Ties == 1)
                {
                    if (auth == null)
                    {
                        auth = new Pub_AuthorizationDto
                        {
                            UserId = GetBaseUserInfo().ID,
                            PatId = pat.Id,
                            Status = 3,
                            CreateTime = DateTime.Now,
                            ApplyDetailIds = "1,2,3,4",
                            ExamineDetailIds = "1,2,3,4",
                            AuthorizationTime = DateTime.Now,
                            AuthorizationValidity = DateTime.Now.AddYears(100),
                            Source = 0,
                            IsForever = true,
                            IsOneSelf = true
                        };

                        _pubAuthorizationRepository.InsertAuthorization(auth);
                    }
                }

                var detail = auth == null ? new PubAuthorizationView() : auth.MapTo<PubAuthorizationView>();

                detail.PatInfo = pat;
                detail.MyUserInfo = myUserInfo;
                detail.UserInfo = users.Where(w => w.ID == item.Key)?.FirstOrDefault();
                detail.CreateTime = mapdetail.Create_Time;

                result.Add(detail);
            }
            return result;
        }

        public Tuple<bool, string> UpdateAuthorizationStatus(Pub_AuthorizationDto model)
        {
            var data = _pubAuthorizationRepository.GetAuthorizationForId(model.Id);
            if (data == null)
            {
                return new Tuple<bool, string>(true, "");
            }
            if (data.Status != 1)
            {
                return new Tuple<bool, string>(true, "");
            }
            var res = _pubAuthorizationRepository.UpdateAuthorizationStatus(model.Id, 2);
            if (res > 0)
            {
                return new Tuple<bool, string>(true, "");
            }
            return new Tuple<bool, string>(false, "");
        }

        public bool RelieveAuthorization(int id)
        {
            var (userId, patId) = _pubAuthorizationRepository.GetUserIdPatIdByAuthorizationId(id);

            _pubAuthorizationRepository.InvalidAuthorization(userId, patId);
            return true;
        }

        public bool InitQueue()
        {
            var pushmodel = new RabbitMsgModel<string> { Key = RabbitMQQueue.Test, Data = "test" };
            //_rabbitMQService.Publish<string>(pushmodel, 1 * 1 * 1000, 60 * 60 * 1000);
            //_rabbitMQService.Publish<string>(pushmodel, 60 * 60 * 1000);
            return true;
        }

        public BaseResponse<bool> CancelOutApt(int id)
        {
            BaseResponse<bool> response = new BaseResponse<bool>();
            var outAptInfo = _outAptInfoRepository.GetOutAptInfo(id);
            if (outAptInfo == null)
            {
                response.Code = 0;
                response.Data = false;
                response.Msg = "未获取到就诊信息";
                return response;
            }
            _logger.LogInformation("CancelOutApt:parms:" + id);
            var user = _pubUserInfoRepository.SelectByPrimaryKey(outAptInfo.Apply_User_Id);
            if (user != null)
            {
                //发送短信
                var pubPatInfo = _pubPatInfoRepository.SelectById(outAptInfo.Pat_Id);
                var tcret = _tCService.CancelAppt(outAptInfo.Apt_Usrn, outAptInfo.Apt_Usrn);
                _logger.LogInformation("CancelOutApt:usrn " + outAptInfo.Apt_Usrn + "取消返回: " + tcret);
                _outAptInfoRepository.UpdateOutAptInnerStatus(outAptInfo.Id, 2, true);
                Dic_Hos hos = _dicHosRepository.SelectByPrimaryKey(outAptInfo.Hos_Id);
                if (outAptInfo.Status != 0)
                {
                    if (pubPatInfo.Pat_Name.IsChinese())
                    {
                        _orderService.PushUserMessage(user, "6", "您有一条新的消息", $"您{outAptInfo.Apt_Time.Value.Month}月{outAptInfo.Apt_Time.Value.Day}日的预约已取消");

                        //发送中文短信 
                        var zh_content = aptUserCancelSmsTemplateCN.Replace("[name]", pubPatInfo.Pat_Name)
                            .Replace("[date]", Convert.ToDateTime(outAptInfo.Apt_Time).ToString("yyyy年MM月dd日 HH:mm"))
                            .Replace("[addr]", hos.CN_SMS_Addr);
                        _zhuTongSMSService.SendSMS(pubPatInfo.Phone_NO, zh_content);
                    }
                    else
                    {
                        _orderService.PushUserMessage(user, "6", "Your have a new message", $"Your appointment on{outAptInfo.Apt_Time.Value.Month}month{outAptInfo.Apt_Time.Value.Day}day has been cancelled");

                        //发送英文短信
                        var en_content = aptUserCancelSmsTemplateEN.Replace("[name]", pubPatInfo.Pat_Name)
                            .Replace("[date]", Convert.ToDateTime(outAptInfo.Apt_Time).ToString("yyyy年MM月dd日 HH:mm"))
                            .Replace("[addr]", hos.EN_SMS_Addr);
                        _zhuTongSMSService.SendSMS(pubPatInfo?.Phone_NO, en_content, false);

                    }
                }
            }
            response.Data = true;
            response.Msg = "成功";
            response.Code = 1;
            return response;
        }
    }
}
