using DocumentFormat.OpenXml.Office.CoverPageProps;
using Hotline.Application.Bulletin;
using Hotline.Application.Identity;
using Hotline.Application.OrderApp;
using Hotline.Article;
using Hotline.Caching.Interfaces;
using Hotline.Configurations;
using Hotline.KnowledgeBase;
using Hotline.Orders;
using Hotline.Push.Notifies;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Settings;
using Hotline.Settings.Hotspots;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Identity;
using Hotline.Share.Dtos.Schedulings;
using Hotline.Share.Dtos.WebPortal;
using Hotline.Share.Enums.KnowledgeBase;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Push;
using Hotline.Share.Tools;
using Hotline.Tools;
using Hotline.Users;
using Hotline.WebPortal;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using NPOI.XWPF.UserModel;
using SqlSugar;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using XF.Domain.Authentications;
using XF.Domain.Cache;
using XF.Domain.Exceptions;
using XF.Domain.Filters;
using XF.Domain.Repository;

namespace Hotline.Api.Controllers
{
    public class FwThirdController : BaseController
    {
        #region 注入

        private readonly IMapper _mapper;
        private readonly IMediator _mediator;
        private readonly IRepository<Bulletin> _bulletinRepository;
        private readonly IRepository<WebUserRegister> _webUserRegisterRepository;
        private readonly IRepository<WebUserAuth> _webUserAuthRepository;
        private readonly IRepository<WebFlowAccept> _webFlowAcceptRepository;
        private readonly ITypedCache<VerificationPic> _verificationPic;
        private readonly ITypedCache<WriteLettersSendSmsDto> _writeLettersSendSms;
        private readonly IRepository<Hotspot> _hotspotRepository;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly IRepository<OrderPublish> _orderPublishRepository;
        private readonly IOrderRepository _orderRepository;
        private readonly IRepository<OrderVisit> _orderVisitRepository;
        private readonly IRepository<Order> _orderListRepository;
        private readonly IRepository<User> _userRepository;
        private readonly IOrderApplication _orderApplication;
        private readonly ISessionContext _sessionContext;
        private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
        private readonly IBulletinApplication _bulletinApplication;
        private readonly IRepository<OldPublicData> _oldPublicDataRepository;
        private readonly IRepository<KnowledgeType> _knowledgeTypeRepository;
        private readonly IRepository<Knowledge> _knowledgeRepository;
        private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
        private readonly ITypedCache<string> _getVailData;
        private readonly IRepository<KnowledgeWord> _knowledgeWordRepository;
        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
        private readonly IIdentityAppService _identityAppService;
        private readonly IHttpClientFactory _httpClientFactory;

        public FwThirdController(IMapper mapper,
            IMediator mediator,
            IRepository<Bulletin> bulletinRepository,
            IRepository<WebUserRegister> webUserRegisterRepository,
            IRepository<WebUserAuth> webUserAuthRepository,
            IRepository<WebFlowAccept> webFlowAcceptRepository,
            ITypedCache<VerificationPic> verificationPic,
            ITypedCache<WriteLettersSendSmsDto> writeLettersSendSms,
            IRepository<Hotspot> hotspotRepository,
            ISystemSettingCacheManager systemSettingCacheManager,
            IRepository<OrderPublish> orderPublishRepository,
            IOrderRepository orderRepository,
            IRepository<OrderVisit> orderVisitRepository,
            IRepository<Order> orderListRepository,
            IRepository<User> userRepository,
            IOrderApplication orderApplication,
            ISessionContext sessionContext,
            IRepository<OrderVisitDetail> orderVisitDetailRepository,
            IBulletinApplication bulletinApplication,
            IRepository<OldPublicData> oldPublicDataRepository,
            IRepository<KnowledgeType> knowledgeTypeRepository,
            IRepository<Knowledge> knowledgeRepository,
            ISystemDicDataCacheManager systemDicDataCacheManager,
            IOptionsSnapshot<AppConfiguration> appOptions,
            ITypedCache<string> getVailData,
            IRepository<KnowledgeWord> knowledgeWordRepository,
            ISystemDicDataCacheManager sysDicDataCacheManager,
            IIdentityAppService identityAppService,
            IHttpClientFactory httpClientFactory
            )
        {
            _mapper = mapper;
            _mediator = mediator;
            _bulletinRepository = bulletinRepository;
            _webUserRegisterRepository = webUserRegisterRepository;
            _webUserAuthRepository = webUserAuthRepository;
            _webFlowAcceptRepository = webFlowAcceptRepository;
            _verificationPic = verificationPic;
            _writeLettersSendSms = writeLettersSendSms;
            _hotspotRepository = hotspotRepository;
            _systemSettingCacheManager = systemSettingCacheManager;
            _orderPublishRepository = orderPublishRepository;
            _orderRepository = orderRepository;
            _orderVisitRepository = orderVisitRepository;
            _userRepository = userRepository;
            _orderListRepository = orderListRepository;
            _orderApplication = orderApplication;
            _sessionContext = sessionContext;
            _orderVisitDetailRepository = orderVisitDetailRepository;
            _bulletinApplication = bulletinApplication;
            _oldPublicDataRepository = oldPublicDataRepository;
            _knowledgeTypeRepository = knowledgeTypeRepository;
            _knowledgeRepository = knowledgeRepository;
            _systemDicDataCacheManager = systemDicDataCacheManager;
            _appOptions = appOptions;
            _getVailData = getVailData;
            _knowledgeWordRepository = knowledgeWordRepository;
            _sysDicDataCacheManager = sysDicDataCacheManager;
            _identityAppService = identityAppService;
            _httpClientFactory = httpClientFactory;
        }

        #endregion

        #region 获取Token

        [AllowAnonymous]
        [HttpPost("gettoken")]
        public async Task<string> LoginWithoutCrypt([FromBody] LoginDto dto)
        {
            return await _identityAppService.LoginAsync(dto, HttpContext.RequestAborted);
        }

        #endregion


        #region 自贡门户查询接口

        #region 4.2 受理统计

        /// <summary>
        /// 受理统计
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getacceptancetypestatisticsbymonth")]
        public async Task<List<OrderFormCount>> GetAcceptanceTypeStatisticsByMonth([FromBody] OrderFormByMonthDto dto)
        {
            if (string.IsNullOrEmpty(dto.StartTime))
                dto.StartTime = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");

            if (string.IsNullOrEmpty(dto.EndTime))
                dto.EndTime = DateTime.Now.ToString("yyyy-MM-dd 23:59:59");

            //查询待
            var listType = await _orderRepository.Queryable()
                .Where(p => p.CreationTime >= Convert.ToDateTime(dto.StartTime) && p.CreationTime <= Convert.ToDateTime(dto.EndTime) && p.Status > EOrderStatus.WaitForAccept)
                .Select(it => new
                {
                    it.AcceptType,
                    it.AcceptTypeCode
                })
                .MergeTable()//将查询出来的结果合并成一个新表
                 .GroupBy(it => new { it.AcceptType, it.AcceptTypeCode })//对新表进行分组
                 .Select(it => new
                 {
                     name = it.AcceptType,
                     value = SqlFunc.AggregateCount(it.AcceptTypeCode)
                 })
                 .ToListAsync();
            var formAcceptanceCount = _mapper.Map<List<OrderFormCount>>(listType);

            if (_appOptions.Value.IsZiGong)
            {
                List<OrderFormCount> orderForms = new List<OrderFormCount>();
                List<string> fromName = ["咨询", "投诉", "求助", "建议", "举报", "表扬", "申报"];
                foreach (var form in fromName)
                {
                    var data = formAcceptanceCount.FirstOrDefault(p => p.name == form);
                    orderForms.Add(new OrderFormCount()
                    {
                        name = form,
                        value = data == null ? 0 : data.value
                    });
                }
                return orderForms;
            }


            return formAcceptanceCount;
        }

        #endregion

        #region 4.3 办理统计

        /// <summary>
        /// 办理统计
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getacceptancetypestatisticsbymonthend")]
        public async Task<List<OrderFormCount>> GetAcceptanceTypeStatisticsByMonthEnd([FromBody] OrderFormByMonthDto dto)
        {
            if (string.IsNullOrEmpty(dto.StartTime))
                dto.StartTime = DateTime.Now.ToString("yyyy-MM-dd 00:00:00");

            if (string.IsNullOrEmpty(dto.EndTime))
                dto.EndTime = DateTime.Now.ToString("yyyy-MM-dd 23:59:59");

            //数据查询
            var listFileType = await _orderRepository.Queryable()
                .Where(p => p.FiledTime >= Convert.ToDateTime(dto.StartTime) && p.FiledTime <= Convert.ToDateTime(dto.EndTime) && p.Status >= EOrderStatus.Visited)
                .Select(it => new
                {
                    it.AcceptType,
                    it.AcceptTypeCode
                })
                .MergeTable()//将查询出来的结果合并成一个新表
                 .GroupBy(it => new { it.AcceptType, it.AcceptTypeCode })//对新表进行分组
                 .Select(it => new
                 {
                     name = it.AcceptType,
                     value = SqlFunc.AggregateCount(it.AcceptTypeCode)
                 })
                 .ToListAsync();

            var formFileCount = _mapper.Map<List<OrderFormCount>>(listFileType);
            if (_appOptions.Value.IsZiGong)
            {
                List<OrderFormCount> orderForms = new List<OrderFormCount>();
                List<string> fromName = ["咨询", "投诉", "求助", "建议", "举报", "表扬", "申报"];
                foreach (var form in fromName)
                {
                    var data = formFileCount.FirstOrDefault(p => p.name == form);
                    orderForms.Add(new OrderFormCount()
                    {
                        name = form,
                        value = data == null ? 0 : data.value
                    });
                }
                return orderForms;
            }
            return formFileCount;
        }

        #endregion

        #region 4.4~5 公告通知、工作简报

        /// <summary>
        /// 公告通知、工作简报
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getarticlelistbynum")]
        public async Task<IReadOnlyList<DataListTopDto>> GetArticleListByNum([FromBody] ArticleIdByNumDto dto)
        {
            if (string.IsNullOrEmpty(dto.PushRanges))
                dto.PushRanges = "2";

            var items = await _bulletinRepository.Queryable()
                .Where(p => p.LoseEfficacyTime >= DateTime.Now)
                .Where(p => p.IsArrive == true)
                .Where(p => SqlFunc.JsonListObjectAny(p.PushRanges, "Key", dto.PushRanges))
                //  .Where(p => p.BulletinTypeId == dto.BulletinTypeId)
                .WhereIF(!string.IsNullOrEmpty(dto.BulletinTypeId), p => p.BulletinTypeId == dto.BulletinTypeId)
                .WhereIF(!string.IsNullOrEmpty(dto.CheckChar), p => p.Content.Contains(dto.CheckChar))
                .WhereIF(!string.IsNullOrEmpty(dto.BulletinDisplayLocation), p => SqlFunc.JsonListObjectAny(p.DisplayLocation, "Key", dto.BulletinDisplayLocation))
                .OrderByDescending(p => p.CreationTime)
                .Select(it => new
                {
                    DataID = it.Id,
                    it.Title,
                    CreateDate = it.CreationTime,
                    it.Content,
                    it.BulletinTypeName
                })
                .Take(dto.Num)
                .ToListAsync();

            return _mapper.Map<IReadOnlyList<DataListTopDto>>(items);
        }

        /// <summary>
        /// 公告通知、工作简报详情
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getarticledetails")]
        public async Task<List<ArticleDetailsDto>> GetArticleDetails([FromBody] ArticleIdDto dto)
        {
            var data = await _bulletinRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted);
            ArticleDetailsDto detailsDto = null;
            if (data != null)
            {
                data.ReadedNum = data.ReadedNum++;
                await _bulletinRepository.UpdateAsync(data, HttpContext.RequestAborted);

                detailsDto = new()
                {
                    NoticeID = data.Id,
                    NoticeTypeName = data.BulletinTypeName,
                    NoticeTitle = data.Title,
                    NoticeBMName = data.SourceOrgName,
                    NoticeCreateDate = data.CreationTime,
                    NoticeRCount = data.ReadedNum,
                    WNED_VideoUrl = "",
                    NoticeContent = data.Content
                };

                if (data != null && !string.IsNullOrEmpty(data.Content))
                    data.Content = _bulletinApplication.GetSiteUrls(data.Content);
            }
            else
                detailsDto = new();
            List<ArticleDetailsDto> dataDto = new() { detailsDto };
            return dataDto;
        }

        #endregion

        #region 4.6 信件选登

        /// <summary>
        /// 查询工单发布后公开的数据
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("get_order_list_publish_all")]
        public async Task<OrderListReturnDto> GetOrderByListAllOpen([FromBody] QueryOrderListDto dto)
        {
            var queryNew = _orderPublishRepository.Queryable()
                .LeftJoin<Order>((op, p) => p.Id == op.OrderId)
                .Where((op, p) => op.PublishState == true)
                .WhereIF(!string.IsNullOrEmpty(dto.FlowCode), (op, p) => p.No == dto.FlowCode)
                .WhereIF(!string.IsNullOrEmpty(dto.FlowName), (op, p) => op.ArrangeTitle.Contains(dto.FlowName))
                .WhereIF(!string.IsNullOrEmpty(dto.FlowSType), (op, p) => p.AcceptTypeCode == dto.FlowSType)
                .WhereIF(!string.IsNullOrEmpty(dto.FlowRType), (op, p) => p.HotspotId == dto.FlowRType)
                .WhereIF(!string.IsNullOrEmpty(dto.FlowSDate), (op, p) => p.StartTime >= DateTime.Parse(DateTime.Parse(dto.FlowSDate).ToString("yyyy-MM-dd 00:00:00")))//dto.FlowSDate
                .WhereIF(!string.IsNullOrEmpty(dto.FlowEDate), (op, p) => p.StartTime <= DateTime.Parse(DateTime.Parse(dto.FlowEDate).ToString("yyyy-MM-dd 00:00:00")))// dto.FlowEDate
                .WhereIF(!string.IsNullOrEmpty(dto.FlowFrom), (op, p) => p.FromName.Contains(dto.FlowFrom))
                .WhereIF(dto.IdentityType.HasValue, (op, p) => p.IdentityType == dto.IdentityType)
                .OrderByDescending((op, p) => op.CreationTime)
               .Select((op, p) => new OrderListDto
               {
                   FlowID = p.Id,
                   FlowCode = p.No,
                   FlowPwd = p.Password,
                   FlowTitle = op.ArrangeTitle,
                   FlowFromName = p.SourceChannel,
                   FlowPurTypeName = p.AcceptType,
                   ConTypeName = p.HotspotName,
                   FlowAddDate = p.CreationTime,
                   PubDate = op.CreationTime,
                   RSFlagName = p.Status >= EOrderStatus.Filed ? "办理完成" : "办理中"
               });

            //var queryold = _oldPublicDataRepository.Queryable()
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowCode), p => p.OrderNo == dto.FlowCode)
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowName), p => p.Title.Contains(dto.FlowName))
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowSType), p => p.AcceptTypeCode == dto.FlowSType)
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowRType), p => p.HotspotId == dto.FlowRType)
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowSDate), p => p.AcceptTime >= DateTime.Parse(DateTime.Parse(dto.FlowSDate).ToString("yyyy-MM-dd 00:00:00")))//dto.FlowSDate
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowEDate), p => p.AcceptTime <= DateTime.Parse(DateTime.Parse(dto.FlowEDate).ToString("yyyy-MM-dd 00:00:00")))// dto.FlowEDate
            //          .WhereIF(!string.IsNullOrEmpty(dto.FlowFrom), p => p.FromName.Contains(dto.FlowFrom))
            //          .WhereIF(dto.IdentityType.HasValue, p => p.IdentityType == dto.IdentityType)
            //          .OrderByDescending(p => p.PubDate)
            //            .Select(p => new OrderListDto
            //            {
            //                FlowID = p.OrderId,
            //                FlowCode = p.OrderNo,
            //                FlowPwd = p.OrderPwd,
            //                FlowTitle = p.Title,
            //                FlowFromName = p.SourceChannelCode,
            //                FlowPurTypeName = p.AcceptTypeCode,
            //                ConTypeName = p.HotspotName,
            //                FlowAddDate = p.CreationTime,
            //                PubDate = p.CreationTime,
            //                RSFlagName = p.State == "1" ? "办理完成" : "办理中"
            //            });

            var (total, items) = await queryNew
                //.OrderByDescending(op => op.PubDate)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);

            //计算总页数
            int nPageCount = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(total) / dto.PageSize));
            OrderListReturnDto returnDto = new()
            {
                Total = total,
                PageNum = dto.PageIndex,
                PageCount = nPageCount,
                Data = _mapper.Map<IReadOnlyList<OrderListDto>>(items)
            };

            return returnDto;
        }

        /// <summary>
        /// 办件摘编详情
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getorderdetailbyid")]
        public async Task<OrderDetail> GetOrderDetailById([FromBody] ArticleIdDto dto)
        {
            var data = await _orderRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted);

            var orderDetail = _mapper.Map<OrderDetail>(data);
            if (data != null)
            {
                //如果是省工单或者是省政民互动的工单，市民不能进行评价
                if (data.IsProvince == true || data.SourceChannelCode == "ZMHD")
                    orderDetail.IsProvinceOrder = "1";
                else
                    orderDetail.IsProvinceOrder = "0";

                //获取发布的数据
                var orderPublish = await _orderPublishRepository.GetAsync(p => p.OrderId == data.Id, HttpContext.RequestAborted);
                if (orderPublish != null)
                {
                    orderDetail.PubFlag = "1";
                    orderDetail.FlowTitle = orderPublish.ArrangeTitle;
                    orderDetail.FlowContent = orderPublish.ArrangeContent;
                    orderDetail.FlowResult = orderPublish.ArrangeOpinion;
                    if (orderPublish.PublishState)
                        orderDetail.FlowPubFlagName = "公开";
                }

                //能否进行评价
                var orderVisit = await _orderVisitRepository.GetAsync(p => p.OrderId == data.Id && p.VisitState != EVisitState.None, HttpContext.RequestAborted);
                if (orderVisit == null)
                    orderDetail.VisitType = "0";
                else
                {
                    orderDetail.VisitType = orderVisit.VisitState switch
                    {
                        EVisitState.WaitForVisit => "1",
                        EVisitState.Visited => "2",
                        EVisitState.Visiting or EVisitState.NoSatisfiedWaitForVisit or EVisitState.None => "0",
                        _ => "0",
                    };
                }

            }
            //List<OrderDetail> dataDto = new() { orderDetail };
            return orderDetail;
        }

        #endregion

        #region 4.7 知识库

        #region 知识库分类

        /// <summary>
        /// 知识库分类
        /// </summary>
        /// <returns></returns>
        [HttpPost("getknowledgetype")]
        public async Task<object> GetKnowledgeType()
        {
            //查询知识分类
            var item = await _knowledgeTypeRepository.Queryable()
                   .Where(p => p.ParentId == null || p.ParentId == "")
                   .Select(p => new
                   {
                       SDICT_ID = p.Id,
                       SDICT_Name = p.Name
                   })
                   .ToListAsync();

            //查询知识标签
            var list = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.KnowledgeBaseTags).Select(p => new
            {
                SDICT_Name = p.DicDataName,
                SDICT_ID = p.DicDataName
            }).ToList();

            var rsp = new
            {
                KnowledgeType = item,
                KnowledgeBaseTags = list,
            };
            return rsp;
        }

        #endregion

        #region 知识库查询

        /// <summary>
        /// 知识库查询
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getknowledgelist")]
        public async Task<PagedDto<KnowledgeInfoThirdDto>> GetKnowledgeList([FromBody] QueryKnowledgeList dto)
        {
            var typeSpliceName = string.Empty;
            if (!string.IsNullOrEmpty(dto.KnowledgeTypeId))
            {
                var type = await _knowledgeTypeRepository.GetAsync(x => x.Name == dto.KnowledgeTypeId);
                typeSpliceName = type?.SpliceName;
            }

            var typeSpliceNameTags = string.Empty;
            if (!string.IsNullOrEmpty(dto.KnowledgeBaseTags))
            {
                var type = await _knowledgeWordRepository.GetAsync(x => x.Tag == dto.KnowledgeBaseTags && x.IsEnable == 1);
                typeSpliceNameTags = type?.Id;
            }

            var (total, items) = await _knowledgeRepository.Queryable()
                .Where(p => p.IsPublic == true && p.Status == EKnowledgeStatus.OnShelf)
                .WhereIF(!string.IsNullOrEmpty(dto.Title), p => p.Title.Contains(dto.Title))
                .WhereIF(!string.IsNullOrEmpty(typeSpliceNameTags), p => SqlFunc.JsonArrayAny(p.Keywords, typeSpliceNameTags) == true)
                .WhereIF(dto.KnowledgeType == 1, p => p.KnowledgeType.Any(t => t.KnowledgeTypeSpliceName.EndsWith("营商环境")))
                .OrderByDescending(p => p.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);

            var data = new PagedDto<KnowledgeInfoThirdDto>(total, _mapper.Map<IReadOnlyList<KnowledgeInfoThirdDto>>(items));
            return data;
        }

        #endregion

        #region 知识库详情

        /// <summary>
        /// 知识库详情
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getknowledgeinfo")]
        public async Task<KnowledgeInfoThirdDto> GetKnowledgeInfo([FromBody] QueryKnowledgeInfo dto)
        {
            var data = await _knowledgeRepository.GetAsync(p => p.Id == dto.Id, HttpContext.RequestAborted);
            KnowledgeInfoThirdDto detailsDto = null;
            if (data != null)
            {
                detailsDto = _mapper.Map<KnowledgeInfoThirdDto>(data);

                if (detailsDto != null && !string.IsNullOrEmpty(detailsDto.Content))
                    data.Content = _bulletinApplication.GetSiteUrls(data.Content);
            }
            else
            {
                detailsDto = new();
            }
            return detailsDto;
        }

        #endregion

        #endregion

        #region 4.8.1 工单写信（老版）

        /// <summary>
        /// 工单写信
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("orderacceptance")]
        public async Task<OpenResponse> OrderAcceptance([FromBody] WebFlowAcceptDto dto)
        {
            //电话号码去空格
            if (!string.IsNullOrEmpty(dto.Mobile))
                dto.Mobile = dto.Mobile.Trim();

            string strResult = dto.ValidateObject();
            if (!string.IsNullOrEmpty(strResult))
            {
                return OpenResponse.Ok(WebPortalDeResponse<OrderAcceptanceReturnDto>.Failed("数据验证不通过！"));
            }

            var order = _orderListRepository.Queryable()
                            .Where(x => x.Title == dto.Title)
                            .Where(x => x.SourceChannelCode == "YTW")
                            .Where(x => x.Contact == dto.Mobile)
                            .Select(x => new
                            {
                                No = x.No,
                                Second = SqlFunc.DateDiff(DateType.Second, x.CreationTime, DateTime.Now)
                            }).MergeTable()
                            .Where(x => x.Second < 180)
                            .Any();
            if (order)
            {
                return OpenResponse.Ok(WebPortalDeResponse<OrderAcceptanceReturnDto>.Failed("3分钟内，请勿重复提交工单！"));
            }

            var data = _mapper.Map<Hotline.Share.Dtos.Order.AddOrderDto>(dto);
            data.Source = ESource.WebPortal;
            data.SourceChannel = "因特网";
            data.SourceChannelCode = "YTW";

            //switch (dto.FromID)
            //{
            //    case "2":
            //        data.SourceChannel = "APP";
            //        data.SourceChannelCode = "AP";
            //        data.Source = ESource.APP;
            //        break;
            //    case "3":
            //        data.SourceChannel = "微信小程序";
            //        data.SourceChannelCode = "XCX";
            //        data.Source = ESource.WeChat;
            //        break;
            //    case "9"://宜宾人社专用
            //        data.SourceChannel = "人社APP";
            //        data.SourceChannelCode = "RSAPP";
            //        data.Source = ESource.YBHumanSocietyAPP;
            //        break;
            //    default:
            //        break;
            //}
            if (!string.IsNullOrEmpty(data.LicenceNo))
            {
                data.LicenceTypeCode = "10";
                data.LicenceType = "中华人民共和国居民身份证";
            }
            data.ExternalId = Guid.NewGuid().ToString();

            data.IdentityType = dto.IdentityType;
            data.Transpond = false;
            data.IsEnforcementOrder = false;


            var result = await _orderApplication.ReceiveOrderFromExternalAsync(data, HttpContext.RequestAborted);

            OrderAcceptanceReturnDto returnDto = new();
            if (result != null)
            {
                returnDto.PWD = result.Password;
                returnDto.Code = result.No;
                returnDto.State = "1";

                dto.Pwd = result.Password;
                dto.Code = result.No;
                dto.OrderId = result.Id;
                var dtoData = _mapper.Map<WebFlowAccept>(dto);
                await _webFlowAcceptRepository.AddAsync(dtoData, HttpContext.RequestAborted);

            }
            else
                returnDto.State = "0";

            return OpenResponse.Ok(WebPortalDeResponse<OrderAcceptanceReturnDto>.Success(returnDto));
        }

        #endregion

        #region 4.8.2 附件上传

        /// <summary>
        /// 附件上传
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("uploadfiles")]
        public async Task<GetResultDto> uploadfiles(IFormFile fileData)
        {
            if (fileData == null || fileData.Length == 0)
            {
                return new GetResultDto();
            }

            Stream stream = fileData.OpenReadStream();
            byte[] fileContentBytes = StreamToBytes(stream);
            var client = _httpClientFactory.CreateClient("fileData");

            using (var content = new MultipartFormDataContent())
            {
                var fileContent = new ByteArrayContent(fileContentBytes);
                fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
                {
                    Name = fileData.Name,
                    FileName = fileData.FileName
                };
                content.Add(fileContent, "fileData", fileData.FileName);

                var response = await client.PostAsync($"{_appOptions.Value.FileUpload.Url.TrimEnd('/')}/file/upload?source=HotlineWeb", content);
                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadFromJsonAsync<GetFileDto>();
                    return new GetResultDto()
                    {
                        id = result.result.id,
                        fileName = result.result.fileName,
                        path = result.result.path,
                    };
                }
                else
                {
                    return new GetResultDto();
                }
            }
        }

        #endregion

        #region 4.8.3 工单写信（带验证码）

        /// <summary>
        /// 工单写信
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("orderacceptancesms")]
        public async Task<OrderAcceptanceReturnDto> OrderAcceptanceSms([FromBody] WebFlowAcceptSmsDto dto)
        {
            //电话号码去空格
            if (!string.IsNullOrEmpty(dto.Mobile))
                dto.Mobile = dto.Mobile.Trim();

            string strResult = dto.ValidateObject();
            if (!string.IsNullOrEmpty(strResult))
            {
                throw UserFriendlyException.SameMessage("数据验证不通过");
            }

            if (dto.Mobile.IsPhoneNumber() == false)
            {
                throw UserFriendlyException.SameMessage("请输入正确的手机号");
            }

            string keyTokenSms = "SmsUserWriteKey_" + dto.Mobile + "_" + DateTime.Now.ToString("yyyyMMdd");
            var dataSms = await _writeLettersSendSms.GetAsync(keyTokenSms, HttpContext.RequestAborted);
            if (dataSms != null)
            {
                if (dataSms.SmsCode != dto.SmsCode)
                    throw UserFriendlyException.SameMessage("短信验证码错误！");
            }
            else
            {
                throw UserFriendlyException.SameMessage("短信验证码错误！");
            }

            var order = _orderListRepository.Queryable()
                            .Where(x => x.Title == dto.Title)
                            .Where(x => x.SourceChannelCode == "YTW")
                            .Where(x => x.Contact == dto.Mobile)
                            .Select(x => new
                            {
                                No = x.No,
                                Second = SqlFunc.DateDiff(DateType.Second, x.CreationTime, DateTime.Now)
                            }).MergeTable()
                            .Where(x => x.Second < 180)
                            .Any();
            if (order)
            {
                throw UserFriendlyException.SameMessage("3分钟内，请勿重复提交工单！");
            }

            var data = _mapper.Map<Hotline.Share.Dtos.Order.AddOrderDto>(dto);
            data.Source = ESource.WebPortal;
            data.SourceChannel = "因特网";
            data.SourceChannelCode = "YTW";

            if (!string.IsNullOrEmpty(data.LicenceNo))
            {
                data.LicenceTypeCode = "10";
                data.LicenceType = "中华人民共和国居民身份证";
            }
            data.ExternalId = Guid.NewGuid().ToString();

            data.IdentityType = dto.IdentityType;
            data.Transpond = false;
            data.IsEnforcementOrder = false;


            var result = await _orderApplication.ReceiveOrderFromExternalAsync(data, HttpContext.RequestAborted);

            OrderAcceptanceReturnDto returnDto = new();
            if (result != null)
            {
                returnDto.PWD = result.Password;
                returnDto.Code = result.No;
                returnDto.State = "1";

                dto.Pwd = result.Password;
                dto.Code = result.No;
                dto.OrderId = result.Id;
                var dtoData = _mapper.Map<WebFlowAccept>(dto);
                await _webFlowAcceptRepository.AddAsync(dtoData, HttpContext.RequestAborted);

            }
            else
                returnDto.State = "0";

            return returnDto;
        }

        #endregion

        #region 4.9 工单查询

        /// <summary>
        /// 根据编号和密码查询信件ID
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getorderdetailbyno")]
        public async Task<OrderDetail> GetOrderDetailByNo([FromBody] GetOrderCodePwd dto)
        {
            var data = await _orderRepository.GetAsync(p => p.No == dto.OrderNo && p.Password == dto.Pwd, HttpContext.RequestAborted);
            if (data != null)
            {
                var orderDetail = _mapper.Map<OrderDetail>(data);
                if (data != null)
                {
                    //如果是省工单或者是省政民互动的工单，市民不能进行评价
                    if (data.IsProvince == true || data.SourceChannelCode == "ZMHD")
                        orderDetail.IsProvinceOrder = "1";
                    else
                        orderDetail.IsProvinceOrder = "0";

                    //获取发布的数据
                    var orderPublish = await _orderPublishRepository.GetAsync(p => p.OrderId == data.Id, HttpContext.RequestAborted);
                    if (orderPublish != null)
                    {
                        orderDetail.PubFlag = "1";
                        orderDetail.FlowTitle = orderPublish.ArrangeTitle;
                        orderDetail.FlowContent = orderPublish.ArrangeContent;
                        orderDetail.FlowResult = orderPublish.ArrangeOpinion;
                        if (orderPublish.PublishState)
                            orderDetail.FlowPubFlagName = "公开";
                    }

                    //能否进行评价
                    var orderVisit = await _orderVisitRepository.GetAsync(p => p.OrderId == data.Id && p.VisitState != EVisitState.None, HttpContext.RequestAborted);
                    if (orderVisit == null)
                        orderDetail.VisitType = "0";
                    else
                    {
                        orderDetail.VisitType = orderVisit.VisitState switch
                        {
                            EVisitState.WaitForVisit => "1",
                            EVisitState.Visited => "2",
                            EVisitState.Visiting or EVisitState.NoSatisfiedWaitForVisit or EVisitState.None => "0",
                            _ => "0",
                        };
                    }

                }
                List<OrderDetail> dataDto = new() { orderDetail };
                return orderDetail;
            }
            return new OrderDetail();
        }


        #endregion

        #region 4.10 图片验证码

        /// <summary>
        /// 图片验证码
        /// </summary>
        /// <returns></returns>
        [HttpGet("getverificationcodebypic")]
        public async Task<VerificationPic> GetVerificationCodeByPic()
        {
            var verifyCode = GetVerifyCodeText(5, true, false);                // 验证码
            var base64String = CreateImageAndConvertToBase64(verifyCode);      // 图片Base64
            var guidString = Guid.NewGuid().ToString();                        // Guid

            var data = new VerificationPic()
            {
                base64 = base64String,
                guid = guidString
            };

            // 保存数据到Readis
            string keyToken = "PicUserWriteKey_" + guidString + "_" + verifyCode + "_" + DateTime.Now.ToString("yyyyMMdd");
            await _verificationPic.SetAsync(keyToken, data, TimeSpan.FromHours(1), HttpContext.RequestAborted);

            return data;
        }

        #endregion

        #region 4.11 短信验证码

        /// <summary>
        /// 短信验证码
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("getverificationcodebysms")]
        public async Task<VerificationSms> GetVerificationCodeBySms([FromBody] VerificationPicDto dto)
        {
            if (dto.TelNum.IsPhoneNumber() == false)
            {
                throw UserFriendlyException.SameMessage("请输入正确的手机号");
            }

            // 验证图片验证码是否对
            string keyToken = "PicUserWriteKey_" + dto.guid + "_" + dto.verCode + "_" + DateTime.Now.ToString("yyyyMMdd");
            var data = await _verificationPic.GetAsync(keyToken, HttpContext.RequestAborted);
            if (data == null)
            {
                throw UserFriendlyException.SameMessage("验证码错误");
            }

            var SmsCodeRand = RandomNum();

            // 发送短信验证码
            string keyTokenSms = "SmsUserWriteKey_" + dto.TelNum + "_" + DateTime.Now.ToString("yyyyMMdd");
            var dataSms = await _writeLettersSendSms.GetAsync(keyTokenSms, HttpContext.RequestAborted);
            if (dataSms != null)//已经发过短信
            {
                //是否可以继续发送短信(10次)
                if (dataSms.SendCount > 10)
                    //短信发送超过10条
                    throw UserFriendlyException.SameMessage("短信发送超过10条");

                // 验证是否在两分钟之内
                TimeSpan duration = DateTime.Now - dataSms.AddTime; // 计算时间差
                if ((int)duration.TotalSeconds < 120)
                    // 距离上次发送时间不足两分钟
                    throw UserFriendlyException.SameMessage("距离上次发送时间不足两分钟");

                //修改缓存信息
                dataSms.SendCount++;
                dataSms.SmsCode = SmsCodeRand;
                dataSms.AddTime = DateTime.Now;
            }
            else
            {
                //没有发过短信，直接写入数据
                dataSms = new WriteLettersSendSmsDto
                {
                    AddTime = DateTime.Now,
                    SmsCode = SmsCodeRand,
                    MobileNum = dto.TelNum,
                    SendCount = 1
                };
            }
            //这里发送短信
            var messageDto = new Share.Dtos.Push.MessageDto
            {
                PushBusiness = EPushBusiness.MsgCode,
                ExternalId = "",
                OrderId = "",
                PushPlatform = EPushPlatform.Web,
                Remark = "",
                Name = dto.TelNum,
                TemplateCode = "1008",
                Params = new List<string>() { SmsCodeRand },
                TelNumber = dto.TelNum,

            };
            await _mediator.Publish(new PushMessageNotify(messageDto), HttpContext.RequestAborted);

            //保存短信
            await _writeLettersSendSms.SetAsync(keyTokenSms, dataSms, TimeSpan.FromDays(1), HttpContext.RequestAborted);

            return new VerificationSms()
            {
                TelNum = dto.TelNum,
                SmsCode = SmsCodeRand
            };
        }

        #endregion

        #region 私有方法

        #region 将文件转化为文件流

        /// <summary>
        /// 将文件转化为文件流
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private byte[] StreamToBytes(Stream stream)
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            // 设置当前流的位置为流的开始    
            stream.Seek(0, SeekOrigin.Begin);
            return bytes;
        }

        #endregion

        #region 获取验证码字符串
        /// <summary>
        /// 获取验证码字符串
        /// </summary>
        /// <param name="codeLen">验证码长度</param>
        /// <param name="addUpper">是否添加大写</param>
        /// <param name="addLower">是否添加小写</param>
        /// <returns></returns>
        private string GetVerifyCodeText(int codeLen = 4, bool addUpper = true, bool addLower = true)
        {
            // 返回对象
            string codeText = "";
            if (codeLen < 4)
            {
                codeLen = 4;
            }
            StringBuilder objChars = new StringBuilder();
            StringBuilder objNums = new StringBuilder();
            // 加入数字1-9
            for (int i = 1; i <= 9; i++)
            {
                objNums.Append(i.ToString());
            }
            List<char> notExists = new List<char>();
            notExists.Add('O');
            notExists.Add('o');
            notExists.Add('I');
            notExists.Add('i');
            notExists.Add('L');
            notExists.Add('l');
            notExists.Add('J');
            notExists.Add('j');
            notExists.Add('P');
            notExists.Add('p');
            notExists.Add('G');
            notExists.Add('g');
            // 加入大写字母A-Z，不包括O
            if (addUpper == true)
            {
                char temp = ' ';

                for (int i = 0; i < 26; i++)
                {
                    temp = Convert.ToChar(i + 65);

                    // 如果生成的字母不是'O','o','I','i','L','l','J','j'
                    if (notExists.Contains(temp) == false)
                    {
                        objChars.Append(temp);
                    }
                }
            }

            // 加入小写字母a-z，不包括o
            if (addLower == true)
            {
                char temp = ' ';

                for (int i = 0; i < 26; i++)
                {
                    temp = Convert.ToChar(i + 97);

                    // 如果生成的字母不是'O','o','I','i','L','l','J','j'
                    if (notExists.Contains(temp) == false)
                    {
                        objChars.Append(temp);
                    }
                }
            }
            // 生成验证码字符串
            {
                int index = 0;
                Random objRandom = new Random();
                StringBuilder objCodes = new StringBuilder();
                for (int i = 0; i < 2; i++)
                {
                    index = objRandom.Next(0, objNums.Length);
                    objCodes.Append(objNums[index]);
                    objNums.Remove(index, 1);
                }
                for (int i = 0; i < codeLen - 2; i++)
                {
                    index = objRandom.Next(0, objChars.Length);
                    objCodes.Append(objChars[index]);
                    objChars.Remove(index, 1);
                }
                for (int i = 0; i < codeLen; i++)
                {
                    index = objRandom.Next(0, objCodes.Length);
                    codeText += objCodes[index];
                    objCodes.Remove(index, 1);
                }
            }
            return codeText;
        }
        #endregion

        #region 创建图片并且转换成base64

        /// <summary>
        /// 创建图片并且转换成base64
        /// </summary>
        /// <param name="verifyCode"></param>
        /// <returns></returns>
        private string CreateImageAndConvertToBase64(string verifyCode)
        {
            var base64String = "";
            try
            {
                // 1. 创建一个新的位图 (100x100像素)
                using (var bitmap = new Bitmap((int)Math.Ceiling((verifyCode.Length * 16.5)), 25))
                {
                    // 2. 使用Graphics对象绘制内容
                    using (var graphics = Graphics.FromImage(bitmap))
                    {
                        Random random = new Random();

                        graphics.Clear(Color.White);

                        for (int i = 0; i < 25; i++)
                        {
                            int x1 = random.Next(bitmap.Width);
                            int x2 = random.Next(bitmap.Width);
                            int y1 = random.Next(bitmap.Height);
                            int y2 = random.Next(bitmap.Height);
                            graphics.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
                        }

                        // 添加一些文本
                        var font = new Font("Arial", 14, (FontStyle.Bold | FontStyle.Italic));
                        System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, bitmap.Width, bitmap.Height), Color.Blue, Color.DarkRed, 1.2f, true);
                        graphics.DrawString(verifyCode, font, brush, 10, 0);

                        for (int i = 0; i < 100; i++)
                        {
                            int x = random.Next(bitmap.Width);
                            int y = random.Next(bitmap.Height);

                            bitmap.SetPixel(x, y, Color.FromArgb(random.Next()));
                        }

                        graphics.DrawRectangle(new Pen(Color.Silver), 0, 0, bitmap.Width - 1, bitmap.Height - 1);
                    }

                    // 保存图片
                    //bitmap.Save("C:\\Users\\PC\\Desktop\\1x1.png", ImageFormat.Png);

                    // 3. 将图像保存到内存流
                    using (var memoryStream = new MemoryStream())
                    {
                        bitmap.Save(memoryStream, ImageFormat.Png);

                        // 4. 将内存流转换为字节数组
                        byte[] imageBytes = memoryStream.ToArray();

                        // 5. 将字节数组转换为Base64字符串
                        base64String = Convert.ToBase64String(imageBytes);
                    }
                }
            }
            catch (Exception)
            {
            }
            return base64String;
        }

        #endregion

        #region 随机生成6位数字

        /// <summary>
        /// 随机生成6位数字
        /// </summary>
        /// <returns></returns>
        private string RandomNum()
        {
            var random = new Random();
            return random.Next(100000, 999999).ToString();
        }

        #endregion

        #endregion

        #endregion

        #region 泸州电信查询接口

        #region 工单信息

        /// <summary>
        /// 工单信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("getOrderResultList")]
        public async Task<IReadOnlyList<Hotline.Share.Dtos.WebPortal.OrderResultDto>> GetOrderResultList([FromBody] DateDto dto)
        {
            TimeSpan timeSpan = dto.EndTime - dto.StartTime;
            if (timeSpan.TotalHours > 24)
            {
                throw UserFriendlyException.SameMessage("开始结束时间不能大于24小时！");
            }

            var items = await _orderListRepository.Queryable()
                .Where(x => x.CreationTime >= dto.StartTime)
                .Where(x => x.CreationTime <= dto.EndTime)
                .OrderByDescending(x => x.CreationTime)
                .Select(it => new
                {
                    Id = it.Id,
                    No = it.No,
                    Title = it.Title,
                    Content = it.Content,
                    ActualHandleOrgName = it.ActualHandleOrgName,
                    CreationTime = it.CreationTime,
                    FromName = it.FromName,
                    FromPhone = string.IsNullOrEmpty(it.FromPhone) ? it.FromPhone : it.Contact
                })
                .ToListAsync();

            return _mapper.Map<IReadOnlyList<Hotline.Share.Dtos.WebPortal.OrderResultDto>>(items);
        }

        #endregion

        #region 评价信息

        /// <summary>
        /// 评价信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("getVisitResultList")]
        public async Task<IReadOnlyList<Hotline.Share.Dtos.WebPortal.VisitResultDto>> GetVisitResultList([FromBody] DateDto dto)
        {
            TimeSpan timeSpan = dto.EndTime - dto.StartTime;
            if (timeSpan.TotalHours > 24)
            {
                throw UserFriendlyException.SameMessage("开始结束时间不能大于24小时！");
            }

            var items = await _orderVisitRepository.Queryable()
                .Includes(x => x.OrderVisitDetails)
                .LeftJoin<OrderPublish>((x, op) => x.OrderId == op.OrderId)
                .Where(x => x.CreationTime >= dto.StartTime)
                .Where(x => x.CreationTime <= dto.EndTime)
                .OrderByDescending(x => x.CreationTime)
                .Select((x, op) => new
                {
                    OrderID = x.OrderId,
                    NowEvaluate = x.NowEvaluate,
                    VisitContent = x.OrderVisitDetails.Where(n => n.VisitTarget == EVisitTarget.Org || n.VisitTarget == EVisitTarget.Seat).Select(s => s.VisitContent).First(),
                    VisitTime = x.VisitTime,
                    VisitName = x.Employee.Name,
                    PublishState = op.PublishState
                })
                .ToListAsync();

            return _mapper.Map<IReadOnlyList<Hotline.Share.Dtos.WebPortal.VisitResultDto>>(items);
        }

        #endregion

        #region 账号信息

        /// <summary>
        /// 账号信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("getUserResultList")]
        public async Task<IReadOnlyList<Hotline.Share.Dtos.WebPortal.UserResultDto>> GetUserResultList()
        {
            var items = await _userRepository.Queryable()
                .OrderByDescending(x => x.CreationTime)
                .Select(it => new
                {
                    UUID = it.Id,
                    Name = it.Name
                })
                .ToListAsync();

            return _mapper.Map<IReadOnlyList<Hotline.Share.Dtos.WebPortal.UserResultDto>>(items);
        }

        #endregion

        #endregion

    }
}
