using DocumentFormat.OpenXml.Drawing.Charts;
using DocumentFormat.OpenXml.Drawing.Diagrams;
using DocumentFormat.OpenXml.Vml;
using DocumentFormat.OpenXml.Wordprocessing;
using Hotline.Application.Early;
using Hotline.Application.Tools;
using Hotline.Caching.Interfaces;
using Hotline.Caching.Services;
using Hotline.Early;
using Hotline.File;
using Hotline.Orders;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Early;
using Hotline.Share.Dtos.ExportWord;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.Article;
using Hotline.Share.Enums.Early;
using Hotline.Share.Enums.Order;
using Hotline.Share.Tools;
using MapsterMapper;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.Threading;
using XF.Domain.Authentications;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using XF.Utility.EnumExtensions;

namespace Hotline.Api.Controllers
{
    public class EarlyController: BaseController
    {
        private readonly IRepository<EarlyWarningSetting> _earlyWarningRepository;
        private readonly IMapper _mapper;
        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
        private readonly IRepository<OrderWord> _orderWrodRepository;
        private readonly IRepository<EarlyWarningOrder> _earlyWarningOrderRepository;
        private readonly IRepository<EarlyWarningOrderDetail> _earlyWarningOrderDetailRepository;
        private readonly IRepository<EarlyWarningPush> _earlyWarningPushRepository;
        private readonly IRepository<EarlyWarningPushDetail> _earlyWarningPushDetailRepository;
        private readonly IEarlyReportProvder _earlyReportProvder;
        private readonly IFileDomainService _fileDomainService;
        private readonly ISessionContext _sessionContext;
        private readonly IOrderRepository _orderRepository;



        public EarlyController(IRepository<EarlyWarningSetting> earlyWarningRepository, IMapper mapper, ISystemDicDataCacheManager sysDicDataCacheManager, IRepository<OrderWord> orderWrodRepository, IRepository<EarlyWarningOrder> earlyWarningOrderRepository, IRepository<EarlyWarningOrderDetail> earlyWarningOrderDetailRepository, IRepository<EarlyWarningPush> earlyWarningPushRepository, IRepository<EarlyWarningPushDetail> earlyWarningPushDetailRepository, IEarlyReportProvder earlyReportProvder,IFileDomainService fileDomainService, ISessionContext sessionContext, IOrderRepository orderRepository)
        {
            _earlyWarningRepository = earlyWarningRepository;
            _mapper = mapper;
            _sysDicDataCacheManager = sysDicDataCacheManager;
            _orderWrodRepository = orderWrodRepository;
            _earlyWarningOrderRepository = earlyWarningOrderRepository;
            _earlyWarningOrderDetailRepository = earlyWarningOrderDetailRepository;
            _earlyWarningPushRepository = earlyWarningPushRepository;
            _earlyWarningPushDetailRepository = earlyWarningPushDetailRepository;
            this._earlyReportProvder = earlyReportProvder;
            this._fileDomainService = fileDomainService;
            _sessionContext = sessionContext;
            _orderRepository = orderRepository;
        }

        #region 预警设置

        /// <summary>
        /// 预警设置列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("earlysetting-pagelist")]
        public async Task<PagedDto<EarlySettingDto>> EarlySettingPageList([FromQuery]EarlySettingPageListRequest dto)
        {
            var (total,items) = await _earlyWarningRepository.Queryable()
                .WhereIF(string.IsNullOrEmpty(dto.EarlyWarningName)== false, d => d.EarlyWarningName.Contains(dto.EarlyWarningName))
                .WhereIF(string.IsNullOrEmpty(dto.EarlyWarningLevelValue)==false ,d=> d.EarlyWarningLevelValue == dto.EarlyWarningLevelValue)
                .WhereIF(dto.IsEnable.HasValue,d=>d.IsEnable == dto.IsEnable).ToPagedListAsync(dto.PageIndex,dto.PageSize,HttpContext.RequestAborted);

            return new PagedDto<EarlySettingDto>(total, _mapper.Map<IReadOnlyList<EarlySettingDto>>(items));
        }

        /// <summary>
        /// 新增预警设置
        /// </summary>
        /// <returns></returns>
        [HttpPost("add-ealysetting")]
        public async Task AddEarlySetting([FromBody] AddEarlySettingRequest dto)
        {
            var earlySetting = _mapper.Map<EarlyWarningSetting>(dto);
            await _earlyWarningRepository.AddAsync(earlySetting,HttpContext.RequestAborted);
        }

        /// <summary>
        /// 修改预警设置
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("update-ealysetting")]
        public async Task UpdateEarlySetting([FromBody] UpdateEarlySettingRequest dto)
        {
            var model = await _earlyWarningRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效信息");
            _mapper.Map(dto, model);
            await _earlyWarningRepository.UpdateAsync(model, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 逻辑删除预警设置
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("del-ealysetting")]
        public async Task DelEarlySetting([FromQuery]string id)
        {
            var model = await _earlyWarningRepository.GetAsync(id, HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效信息");
            await _earlyWarningRepository.RemoveAsync(model,true, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取预警设置
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("get-earlysetting/{id}")]
        public async Task<EarlySettingDto> GetEarlySetting(string id)
        {
            var model = await _earlyWarningRepository.GetAsync(id, HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效信息");
            return _mapper.Map<EarlySettingDto>(model);
        }

        /// <summary>
        /// 预警设置基础数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("earlysetting-basedata")]
        public object EarlySettingBaseData()
        {
            return new
            {
                EarlyWarningLevel = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.EarlyWarningLevel),
                EarlyWarningType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.EarlyWarningType),
                EFrequency = EnumExts.GetDescriptions<EFrequency>(),
                ECompareType = EnumExts.GetDescriptions<ECompareType>(),
                SensitiveWords = _orderWrodRepository.Queryable().Where(x => x.IsEnable == 1 && x.Classify.Contains("敏感标签")).Select(x => x.Tag).ToList(),
                ENextWhere = EnumExts.GetDescriptions<ENextWhere>(),
            };
        }


        #endregion

        #region 预警管理

        /// <summary>
        /// 预警管理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("earlyorder-pagelist")]
        public async Task<PagedDto<EarlyOrderDto>> EarlyOrderPageList([FromQuery]EarlyOrderPageListRequest dto)
        {
            var (total,items) = await _earlyWarningOrderRepository.Queryable()
                .Includes(d => d.EarlyWarningSetting)
                .Includes(d=>d.EarlyWarningOrderDetails)
                .WhereIF(string.IsNullOrEmpty(dto.EarlyWarningName) == false, d => d.EarlyWarningSetting.EarlyWarningName.Contains(dto.EarlyWarningName))
                .WhereIF(string.IsNullOrEmpty(dto.EarlyWarningLevelValue) == false, d => d.EarlyWarningSetting.EarlyWarningLevelValue == dto.EarlyWarningLevelValue)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<EarlyOrderDto>(total, _mapper.Map<IReadOnlyList<EarlyOrderDto>>(items));
        }

        /// <summary>
        /// 获取预警管理对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("get-earlyorder/{id}")]
        public async Task<EarlyOrderDto> GetEarlyOrder(string id)
        {
            var model = await _earlyWarningOrderRepository.Queryable()
                .Includes(x=>x.EarlyWarningSetting)
                .Includes(x=>x.EarlyWarningOrderDetails,d=>d.Order)
                .Where(x=>x.Id == id).FirstAsync(HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效信息");
            return _mapper.Map<EarlyOrderDto>(model);
        }


        #endregion

        #region 推送管理

        /// <summary>
        /// 推送报告列表基础数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("earlypush-pagelist-basedata")]
        public async Task<object> EarlyPushPageListBaseData()
        {
            return new
            {
                EarlyPushStatus = EnumExts.GetDescriptions<EEarlyPushStatus>()
            };
        }

        /// <summary>
        /// 推送报告列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("earlypush-pagelist")]
        public async Task<PagedDto<EarlyPushDto>> EarlyPushPageList([FromQuery] EarlyPushPageListRequest dto)
        {
            var (total, items) = await _earlyWarningPushRepository.Queryable()
               .WhereIF(string.IsNullOrEmpty(dto.EarlyWarningPushName) == false, d => d.EarlyWarningPushName.Contains(dto.EarlyWarningPushName))
               .WhereIF(dto.EarlyPushStatus.HasValue, d => d.EarlyPushStatus == dto.EarlyPushStatus)
               .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);

            return new PagedDto<EarlyPushDto>(total, _mapper.Map<IReadOnlyList<EarlyPushDto>>(items));
        }

        /// <summary>
        /// 可以选择推送的工单
        /// </summary>
        /// <returns></returns>
        [HttpGet("early-canchooseorderbasedata")]
        public async Task<object> EarlyCanChooseOrderBaseData()
        {
            return new
            {
                OrderStatus = EnumExts.GetDescriptions<EOrderStatus>(),
                OrderPushStatus = EnumExts.GetDescriptions<EOrderPushStatus>().Where(d => new int[] { 2 }.Contains(d.Key) == false).ToList()
            };
        }


        /// <summary>
        /// 可以选择推送的工单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("early-canchooseorder")]
        public async Task<PagedDto<CanChooseOrderRsp>> CanChooseOrder([FromQuery] CanChooseOrderRequest dto)
        {
            var (total,items) = await _earlyWarningOrderDetailRepository.Queryable()
                .Includes(x=>x.Order)
                .Where(x => x.OrderPushStatus != EOrderPushStatus.FiledPush)
                .Where(x=> dto.ChooseOrderId.Contains(x.OrderId) == false)
                .WhereIF(string.IsNullOrEmpty(dto.No)==false,x=>x.Order.No.Contains(dto.No))
                .WhereIF(string.IsNullOrEmpty(dto.Title)==false,x=>x.Order.Title.Contains(dto.Title))
                .WhereIF(dto.OrderStatus.HasValue,x=>x.Order.Status == dto.OrderStatus)
                .WhereIF(dto.OrderPushStatus.HasValue,x=>x.OrderPushStatus == dto.OrderPushStatus)
                .ToPagedListAsync(dto.PageIndex,dto.PageSize,HttpContext.RequestAborted);

            return new PagedDto<CanChooseOrderRsp>(total, _mapper.Map<IReadOnlyList<CanChooseOrderRsp>>(items));
        }

        /// <summary>
        /// 新增推送报告 TODO
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("add-earlypush")]
        public async Task AddEarlyPush([FromBody] AddEarlyPushRequest dto)
        {
            var earlySettingPush = _mapper.Map<EarlyWarningPush>(dto);
            earlySettingPush.EarlyPushStatus = EEarlyPushStatus.Pushed;
            if (dto.OperateModel==1)
            {
                earlySettingPush.EarlyPushStatus = EEarlyPushStatus.Draft;
            }
            if (dto.OperateModel!=1)
            {
                earlySettingPush.PushTime = DateTime.Now;
            }
            if (dto.OperateModel == 3)
            {
                //准备数据
                var reportDto = await GetEarlyReport(dto.EarlyWarningPushDetails,earlySettingPush);               
               
                // 生成推送文件流
                var html = _earlyReportProvder.PushReport(reportDto);

                // 推送文件
                var fileJson =  await _fileDomainService.UploadFileFromMemoryAsync(html.HtmlToWord(), "报表" + EFileType.word.GetFileExtension(), EFileType.word);
               
                //推送生成报告消息TODO
                earlySettingPush.PushReportUrl = "";
            }
            await _earlyWarningPushRepository.AddAsync(earlySettingPush, HttpContext.RequestAborted);
            dto.EarlyWarningPushDetails.ForEach(x =>
            {
                x.EarlyWarningPushId = earlySettingPush.Id;
                if(dto.OperateModel != 1)
                {
                    if(x.Order.Status < EOrderStatus.Filed)
                    {
                        _earlyWarningOrderDetailRepository.Updateable().SetColumns(x => x.OrderPushStatus == EOrderPushStatus.ProcessingPush).Where(x => x.OrderId == x.OrderId);
                    }
                    if (x.Order.Status >= EOrderStatus.Filed)
                    {
                        _earlyWarningOrderDetailRepository.Updateable().SetColumns(x => x.OrderPushStatus == EOrderPushStatus.FiledPush).Where(x => x.OrderId == x.OrderId);
                    }
                }
            });
            var detail = _mapper.Map<List<EarlyWarningPushDetail>>(dto.EarlyWarningPushDetails);
            await _earlyWarningPushDetailRepository.AddRangeAsync(detail,HttpContext.RequestAborted);
        }

        private async Task<EarlyReportDto> GetEarlyReport(List<EarlyWarningPushDetailDto> dto, EarlyWarningPush earlyPush)
        {
            var reportDto = new EarlyReportDto();
            reportDto.ReportName = earlyPush.EarlyWarningPushName;
            reportDto.ReportPushTime = earlyPush.PushTime.Value;
            reportDto.ReportHotDetails = new List<ReportHotDetailDto>();
            List<string> orderIds = dto.Select(x => x.OrderId).ToList();
            //查询所有工单
            var orderList = await _orderRepository.Queryable().Where(x => orderIds.Contains(x.Id)).ToListAsync();

            var result = (from a in orderList
                         join b in dto on a.Id equals b.OrderId
                         select new ReportOrderListDto (){ Id = a.Id, ActualHandleOrgName = a.ActualHandleOrgName, IsSendWord = b.IsSendWord, County = a.County, OneHotspotName = a.HotspotSpliceName.Split("-")[0], HotspotName = a.HotspotName, Status = a.Status,FileOpinion = a.FileOpinion, Content = a.Content }).ToList();

            //Title 热点汇总
            var reportHotDetail = result.GroupBy(x => x.OneHotspotName).ToList();
            reportDto.ReportHotDetails = new List<ReportHotDetailDto>();
            reportHotDetail.ForEach(x =>
            {
                var detail = new ReportHotDetailDto();
                detail.HotName = x.Key;
                detail.Count = x.Count();
                detail.Content = string.Join(",", result.Where(d => d.IsSendWord == true && d.OneHotspotName == x.Key).Select(d => d.Content));
                reportDto.ReportHotDetails.Add(detail);
            });

            //Title 地区汇总
            reportDto.ReportAreaDetails = result.GroupBy(x => x.County).Select(x=> new ReportAreaDetailDto() { AreaName = x.Key,Count = x.Count() }).ToList();

            //附件1：重点诉求处置情况
            reportDto.ReportOrderDetails = result.Where(x => x.Status < EOrderStatus.Filed && x.IsSendWord == true).Select(x => new ReportOrderDetailDto() { OneHotSportName = x.OneHotspotName, HotSportName = x.HotspotName, Content = x.Content, ActualOpinion = "已转发" + x.ActualHandleOrgName + ",正在处理中" }).ToList();

            //附件2：
            //查询往期
            var earlyWarningPushDetail = await _earlyWarningPushDetailRepository.Queryable().Includes(x=>x.EarlyWarningPush).Where(x => result.Select(x => x.Id).Contains(x.OrderId)).ToListAsync();
            var fujianTwoList = (from a in result
                                 join b in earlyWarningPushDetail on a.Id equals b.OrderId
                                 where a.Status>= EOrderStatus.Filed && a.IsSendWord == true
                                 select new ReportFiledOrderDetailDto() { ReportName = b.EarlyWarningPush.EarlyWarningPushName, OneHotSportName = a.OneHotspotName, HotSportName = a.HotspotName,Content = a.Content, ActualOpinion = a.FileOpinion }).ToList();
            reportDto.ReportFiledOrderDetails = fujianTwoList;

            return reportDto;
        }
        /// <summary>
        /// 获取推送报告
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("getearlypush/{id}")]
        public async Task<EarlyPushDto> GetEarlyPush(string id)
        {
            var model = await _earlyWarningPushRepository.Queryable()
                .Includes(x => x.EarlyWarningPushDetails)
                .Includes(x=>x.EarlyWarningPushDetails,d=>d.Order)
                .FirstAsync(HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效信息");
            return _mapper.Map<EarlyPushDto>(model);
        }

        #endregion

        #region 报告接收

        /// <summary>
        /// 报告接收
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("report-receive")]
        public async Task<PagedDto<EarlyPushDto>> ReportReceive([FromQuery] ReportReceiveRequest dto)
        {
            var (total, items) = await _earlyWarningPushRepository.Queryable()
               .WhereIF(string.IsNullOrEmpty(dto.EarlyWarningPushName) == false, d => d.EarlyWarningPushName.Contains(dto.EarlyWarningPushName))
               .Where(d=> d.EarlyPushStatus == EEarlyPushStatus.Pushed && SqlFunc.JsonListObjectAny(d.PushOrgs, "OrgCode", _sessionContext.OrgId))
               .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);

            return new PagedDto<EarlyPushDto>(total, _mapper.Map<IReadOnlyList<EarlyPushDto>>(items));
        }



        #endregion
    }
}
