using Hotline.Api.Filter;
using Hotline.Application.ExportExcel;
using Hotline.Caching.Interfaces;
using Hotline.FlowEngine;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Settings;
using Hotline.Settings.Hotspots;
using Hotline.Settings.TimeLimits;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Hotspots;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.Settings;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Settings;
using MapsterMapper;
using Microsoft.AspNetCore.Mvc;
using NPOI.OpenXmlFormats.Vml;
using SqlSugar;
using StackExchange.Redis;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using XF.Utility.EnumExtensions;

namespace Hotline.Api.Controllers
{
    /// <summary>
    /// 热点
    /// </summary>
    public class HotspotController : BaseController
    {
        private readonly IRepository<Hotspot> _hotspotTypeRepository;
        private readonly IMapper _mapper;
        private readonly ITimeLimitDomainService _timeLimitDomainService;
        private readonly ITimeLimitRepository _timeLimitRepository;
        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
        private readonly IEventCategoryRepository _eventCategoryRepository;
        private readonly IExportApplication _exportApplication;

        public HotspotController(IRepository<Hotspot> hotspotTypeRepository,
            IMapper mapper, ITimeLimitDomainService timeLimitDomainService, ITimeLimitRepository timeLimitRepository, ISystemDicDataCacheManager sysDicDataCacheManager, IEventCategoryRepository eventCategoryRepository, IExportApplication exportApplication)
        {
            _hotspotTypeRepository = hotspotTypeRepository;
            _mapper = mapper;
            _timeLimitDomainService = timeLimitDomainService;
            _timeLimitRepository = timeLimitRepository;
            _sysDicDataCacheManager = sysDicDataCacheManager;
            _eventCategoryRepository = eventCategoryRepository;
            _exportApplication = exportApplication;
        }

        #region 热点
        /// <summary>
        /// 查询子项
        /// </summary>
        [HttpGet("children")]
        public async Task<IReadOnlyList<Hotspot>> GetChildren([FromQuery] string? id)
        {
             var list = await  _hotspotTypeRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(id), x => x.ParentId == id)
                .WhereIF(string.IsNullOrEmpty(id), x => x.ParentId == null || x.ParentId == "")
                .OrderBy(d => d.HotSpotName)
                .Select(x=> new Hotspot
                {
                    Id = x.Id,
                    HotSpotName = x.HotSpotName,
                    ParentId = x.ParentId,
                    HotSpotFullName = x.HotSpotFullName,
                    ProvinceCode = x.ProvinceCode,
                    HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d=>d.ParentId == x.Id).NotAny(),
                    TrunkNum = x.TrunkNum,
                }).ToListAsync();

            return list;
        }

        /// <summary>
        /// 名称检索热点树形
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet("children-hasname")]
        public async Task<IReadOnlyList<Hotspot>> GetChildrenHasName([FromQuery]string name)
        {
            var arr = _hotspotTypeRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(name), x => x.HotSpotFullName.Contains(name)).Select(x=>x.Id).ToList().Cast<object>().ToArray();
            //.ToTreeAsync(x => x.Children, it => it.ParentId, null);
            return await _hotspotTypeRepository.Queryable().Select(x => new Hotspot
            {
                Id = x.Id,
                HotSpotName = x.HotSpotName,
                ParentId = x.ParentId,
                HotSpotFullName = x.HotSpotFullName,
                ProvinceCode = x.ProvinceCode,
                HasChild = SqlFunc.Subqueryable<Hotspot>().Where(d => d.ParentId == x.Id).NotAny(),
                TrunkNum = x.TrunkNum,
			}).ToTreeAsync(x => x.Children, it => it.ParentId,"", arr);
        }



        /// <summary>
        /// 查询热点数据（包含所有根目录及所查热点的所有上级对象）
        /// <remarks>
        /// 编辑页面使用
        /// </remarks>
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}/with-parents")]
        public async Task<IReadOnlyList<Hotspot>> GetWithParents(string id)
        {
            var targetList = await _hotspotTypeRepository.Queryable()
                .ToTreeAsync(d => d.Children, d => d.ParentId, null, new[] { id });
            var topIds = targetList.Select(d => d.Id);
            var hotspots = await _hotspotTypeRepository.Queryable()
                .Where(d => string.IsNullOrEmpty(d.ParentId) && !topIds.Contains(d.Id))
                .ToListAsync();
            hotspots.AddRange(targetList);
            return hotspots.OrderBy(d => d.HotSpotName).ToList();
        }

        #endregion

        #region 事件分类管理
        /// <summary>
        /// 事件全部树形
        /// </summary>
        /// <returns></returns>
        [HttpGet("event/tree")]
        public async Task<IReadOnlyList<EventCategory>> GetEventAllTree()
        {
            return await _eventCategoryRepository.Queryable()
                .OrderBy(d => d.OrderBy)
                .ToTreeAsync(x => x.Children, it => it.ParentId,null);
        }

        /// <summary>
        /// 事件导出
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("event/tree/export")]
		[LogFilterAlpha("导出日志")]
		public async Task<FileStreamResult> GetEventAllTreeExport([FromBody]ExportExcelDto<string> dto)
        {
            var items = await _eventCategoryRepository.Queryable()
                .OrderBy(d => d.OrderBy)
                .ToTreeAsync(x => x.Children, it => it.ParentId, null);
            return _exportApplication.GetExcelFile(dto, items, "事件");
        }

        /// <summary>
        /// 查询子项
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("event/children")]
        public async Task<IReadOnlyList<EventCategory>> GetEventChildren([FromQuery]string? id)
        {
            var list = await _eventCategoryRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(id),x => x.ParentId == id)
                .WhereIF(string.IsNullOrEmpty(id),x=>x.ParentId == null || x.ParentId=="")
                .OrderBy(d => d.EventName)
                .Select(x => new EventCategory
                {
                    Id = x.Id,
                    EventName = x.EventName,
                    ParentId = x.ParentId,
                    EventFullName = x.EventFullName,
                    HasChild = SqlFunc.Subqueryable<EventCategory>().Where(d => d.ParentId == x.Id).NotAny()
                }).ToListAsync();

            return list;
        }

        /// <summary>
        /// 名称检索事件树形
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet("event/children-hasname")]
        public async Task<IReadOnlyList<EventCategory>> GetEventChildrenHasName([FromQuery]string name)
        {
            var arr = _eventCategoryRepository.Queryable()
            .WhereIF(!string.IsNullOrEmpty(name), x => x.EventFullName.Contains(name)).Select(x => x.Id).ToList().Cast<object>().ToArray();
            return await _eventCategoryRepository.Queryable().Select(
                x=> new EventCategory {
                    Id = x.Id,
                    EventName = x.EventName,
                    ParentId = x.ParentId,
                    EventFullName = x.EventFullName,
                    HasChild = SqlFunc.Subqueryable<EventCategory>().Where(d => d.ParentId == x.Id).NotAny()
                }).ToTreeAsync(x => x.Children, it => it.ParentId, "", arr);
        }


        #region 管理接口

        /// <summary>
        /// 新增事件
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("event/add-event")]
        public async Task AddEventCategory([FromBody]AddEventCategoryDto dto)
        {
            //验证重复
            var ishas = await _eventCategoryRepository.AnyAsync(x => x.ParentId == dto.ParentId && x.EventName == dto.EventName);
            if (ishas)
            {
                throw UserFriendlyException.SameMessage("同级别下存在相同名字的事件，不能添加");
            }
            var model = _mapper.Map<EventCategory>(dto);
            (model.Id,model.EventFullName) = await _eventCategoryRepository.GetNewEventCodeAsync(dto.ParentId,model.EventName);
            await _eventCategoryRepository.AddAsync(model, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除事件
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("event/del-event")]
        public async Task DelEventCategory(string[] id)
        {
            var list = await _eventCategoryRepository.Queryable().In(id).ToListAsync(HttpContext.RequestAborted);
            await _eventCategoryRepository.RemoveRangeAsync(list,true, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 修改事件
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("event/modify-event")]
        public async Task ModifyEventCategory([FromBody] ModifyEventCategoryDto dto)
        {
            var model = await _eventCategoryRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效数据");

            model.EventName = dto.EventName;

            var parentModel = await _eventCategoryRepository.GetAsync(model.ParentId, HttpContext.RequestAborted);
            if (parentModel!= null)
            {
                model.EventFullName = parentModel.EventFullName + "-" + model.EventName;
            }
            model.OrderBy = dto.OrderBy;
            await _eventCategoryRepository.UpdateAsync(model, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取事件对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("event")]
        public async Task<EventCategoryDto> GetEventCategory(string id)
        {
            var model = await _eventCategoryRepository.GetAsync(id, HttpContext.RequestAborted);
            if (model == null)
                throw UserFriendlyException.SameMessage("无效数据");
            return _mapper.Map<EventCategoryDto>(model);
        }

        #endregion
        #endregion


        #region 时限管理

        /// <summary>
        /// 获取时限配置页面基础数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("timelimit-basedata")]
        public async Task<object> GetTimeLimitBaseData()
        {
            return new
            {
                //ModuleOptions = WorkflowModule.Modules.ToList(),//todo
                TimeType = EnumExts.GetDescriptions<ETimeType>(),
                BaseData = TimeLimitBaseData.GetBaseData(),

                //AcceptType = EnumExts.GetDescriptions<EAcceptType>(),
                AcceptType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.AcceptType),
                //PushType = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.PushType),
                SourceChannel = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.SourceChannel),
                IdentityType = EnumExts.GetDescriptions<EIdentityType>(),
                OrderType = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.OrderType),
                CertType = _sysDicDataCacheManager.GetSysDicDataCache(TimeLimitBaseDataConsts.LicenceType),
                EmergencyLevel = EnumExts.GetDescriptions<EEmergencyLevel>()
            };
        }

        /// <summary>
        /// 新增时限管理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns>数据主键</returns>
        [HttpPost("add-timelimit")]
        public async Task<string> AddTimeLimit([FromBody] AddTimeLimitDto dto)
        {
            var model = _mapper.Map<TimeLimit>(dto);
            model.TimeLimitState = ETimeLimitState.Draft;
            return await _timeLimitDomainService.AddAsync(model, HttpContext.RequestAborted);
        }


        /// <summary>
        /// 修改时限管理
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("update-timelimit")]
        public async Task UpdateTimeLimit([FromBody] UpdateTimeLimitDto dto)
        {
            var model = _mapper.Map<TimeLimit>(dto);
            await _timeLimitDomainService.UpdateAsync(model, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("timelimit/{id}")]
        public async Task<TimeLimit?> GetTimeLimit(string id)
        {
            return await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
        }


        /// <summary>
        /// 获取时限管理列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("paged-timelimit")]
        public async Task<PagedDto<TimeLimit>> QueryPagedTimeLimit([FromQuery] QueryPagedTimeLimitPagedDto dto)
        {
            var (total, items) = await _timeLimitRepository.Queryable()
                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.TimeLimitName.Contains(dto.Keyword!))
                .OrderByDescending(d => d.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<TimeLimit>(total, _mapper.Map<IReadOnlyList<TimeLimit>>(items));
        }

        /// <summary>
        /// 删除时限（草稿）
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("deltimelimit")]
        public async Task DelTimeLimit(string id)
        {
            var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
            if (model == null)
            {
                throw UserFriendlyException.SameMessage("无效数据");
            }
            if (model.TimeLimitState != ETimeLimitState.Draft)
            {
                throw UserFriendlyException.SameMessage("无法删除，请刷新页面");
            }
            await _timeLimitRepository.RemoveAsync(id, true, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 启用时限
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("enable-timelimit/{id}")]
        public async Task EnableTimeLimit(string id)
        {
            var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
            if (model == null)
            {
                throw UserFriendlyException.SameMessage("无效数据");
            }
            if (model.TimeLimitState == ETimeLimitState.Enable)
            {
                throw UserFriendlyException.SameMessage("该配置已生效");
            }
            var list = await _timeLimitRepository.QueryAsync(x => x.WorkflowCode == model.WorkflowCode && x.TimeLimitState == ETimeLimitState.Enable);
            list.ForEach(x => x.TimeLimitState = ETimeLimitState.Disable);
            model.TimeLimitState = ETimeLimitState.Enable;
            list.Add(model);
            await _timeLimitRepository.UpdateRangeAsync(list, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 禁用时限
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("disable-timelimit/{id}")]
        public async Task DisableTimeLimit(string id)
        {
            var model = await _timeLimitRepository.GetAsync(id, HttpContext.RequestAborted);
            if (model == null)
            {
                throw UserFriendlyException.SameMessage("无效数据");
            }
            if (model.TimeLimitState == ETimeLimitState.Draft)
            {
                throw UserFriendlyException.SameMessage("该配置未生效，无法禁用");
            }
            if (model.TimeLimitState == ETimeLimitState.Disable)
            {
                throw UserFriendlyException.SameMessage("该配置已禁用");
            }
            model.TimeLimitState = ETimeLimitState.Disable;
            await _timeLimitRepository.UpdateAsync(model, HttpContext.RequestAborted);
        }
        #endregion


        #region 工作日设定





        #endregion
    }
}
