using Hotline.Caching.Interfaces;
using MapsterMapper;
using XF.Domain.Authentications;
using XF.Domain.Repository;
using Hotline.Quality;
using Hotline.Permissions;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Microsoft.AspNetCore.Mvc;
using XF.Domain.Exceptions;
using Hotline.Share.Dtos.Quality;
using Hotline.Share.Enums.Quality;
using XF.Utility.EnumExtensions;
using Hotline.Application.Quality;
using Microsoft.AspNetCore.Authorization;
using Hotline.Orders;
using Hotline.Ai.Quality;
using Hotline.Api.Filter;
using Hotline.Application.CallCenter;
using Hotline.CallCenter.Configs;
using Microsoft.Extensions.Options;
using Hotline.Configurations;
using Hotline.CallCenter.Calls;
using System.Linq;
using Hotline.Repository.SqlSugar.Quality;
using Hotline.Caching.Services;
using Hotline.FlowEngine.WorkflowModules;
using Hotline.Settings.TimeLimits;
using Hotline.Share.Enums.Order;

namespace Hotline.Api.Controllers
{
    public class QualityController : BaseController
    {
        private readonly ISessionContext _sessionContext;
        private readonly IMapper _mapper;
        private readonly IQualityRepository _qualitey;
        private readonly IRepository<QualityDetail> _qualiteyDetail;
        private readonly IRepository<QualityItem> _qualiteyItem;
        private readonly IRepository<QualityTemplate> _qualityTemplate;
        private readonly IRepository<QualityTemplateDetail> _qualiteyTemplateDetail;
        private readonly IRepository<QualityProhibited> _qualiteyProhibited;
        private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
        //private readonly IRepository<TrCallRecord> _trCallRecordRepository;
        private readonly IQualityApplication _qualityApplication;
        private readonly IOrderRepository _orderRepository;

        private readonly IServiceProvider _serviceProvider;
        //private readonly IAiQualityService _aiQualityService;

        private readonly ILogger<QualityController> _logger;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly ICallApplication _callApplication;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
        private readonly IRepository<SystemLog> _logRepository;
        private readonly IRepository<QualityTransferRecords> _qualityTransferRecordsRepository;
        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;

        public QualityController(
            ISessionContext sessionContext,
            IMapper mapper,
            IQualityRepository qualitey,
            IRepository<Quality.QualityDetail> qualiteyDetail,
            IRepository<QualityItem> qualiteyItem,
            IRepository<QualityTemplate> qualityTemplate,
            IRepository<QualityTemplateDetail> qualiteyTemplateDetail,
            IRepository<QualityProhibited> qualiteyProhibited,
            ISystemDicDataCacheManager systemDicDataCacheManager,
            //IRepository<TrCallRecord> trCallRecordRepository,
            IQualityApplication qualityApplication,
            IOrderRepository orderRepository,
            //IAiQualityService aiQualityService,
            IServiceProvider serviceProvider,
            ILogger<QualityController> logger,
            ISystemSettingCacheManager systemSettingCacheManager,
            ICallApplication callApplication,
            IOptionsSnapshot<AppConfiguration> appOptions,
            IRepository<SystemLog> logRepository,
            IRepository<QualityTransferRecords> qualityTransferRecordsRepository,
            ISystemDicDataCacheManager sysDicDataCacheManager)
        {
            _sessionContext = sessionContext;
            _mapper = mapper;
            _qualitey = qualitey;
            _qualiteyDetail = qualiteyDetail;
            _qualiteyItem = qualiteyItem;
            _qualityTemplate = qualityTemplate;
            _qualiteyTemplateDetail = qualiteyTemplateDetail;
            _qualiteyProhibited = qualiteyProhibited;
            _systemDicDataCacheManager = systemDicDataCacheManager;
            //_trCallRecordRepository = trCallRecordRepository;
            _qualityApplication = qualityApplication;
            _orderRepository = orderRepository;
            _serviceProvider = serviceProvider;
            //_aiQualityService = aiQualityService;
            _logger = logger;
            _systemSettingCacheManager = systemSettingCacheManager;
            _callApplication = callApplication;
            _appOptions = appOptions;
            _logRepository = logRepository;
            _qualityTransferRecordsRepository = qualityTransferRecordsRepository;
            _sysDicDataCacheManager = sysDicDataCacheManager;
        }
        #region 质检管理
        /// <summary>
        /// 删除质检
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete]
        public async Task Delete([FromBody] DeleteQualityDto dto)
        {
            foreach (var Id in dto.Ids)
            {
                await _qualitey.RemoveAsync(x => x.Id == Id);
                List<QualityDetail> details = await _qualiteyDetail.Queryable().Where(x => x.QualityId == Id).ToListAsync();
                await _qualiteyDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
            }
        }

        /// <summary>
        /// 更新质检
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task Update([FromBody] UpdateQualityDto dto)
        {
            await _qualityApplication.UpdateQualityAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 更新质检
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("transfer")]
        public async Task TransferUpdate([FromBody] TransferUpdate dto)
        {
            await _qualitey.Updateable().SetColumns(x => new Hotline.Quality.Quality { Transfer = dto.Transfer }).Where(x => x.Id == dto.Id).ExecuteCommandAsync(HttpContext.RequestAborted);
        }



        /// <summary>
        /// 获取质检列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("list")]
        public async Task<PagedDto<QualityDto>> List([FromQuery] QualityListDto dto)
        {
            var (total, items) = await _qualitey.Queryable()
                .Includes(x => x.Order)
                .Includes(x => x.Visit)
                .Includes(x => x.Visit, e => e.Employee)
                .Includes(x => x.QualityDetails)
                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!))
                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Order.No.Contains(dto.No!))
                .WhereIF(dto.State.HasValue, x => x.State == dto.State)
                .WhereIF(dto.Source.HasValue, x => x.Source == dto.Source)
                .WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Accepted, x => !string.IsNullOrEmpty(x.Order.CallId))
                .WhereIF(dto.Source.HasValue && dto.Source == EQualitySource.Visit, x => !string.IsNullOrEmpty(x.Visit.CallId))
                .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
                .WhereIF(dto.MaxGrade.HasValue, x => x.Grade <= dto.MaxGrade)
                .WhereIF(dto.MinGrade.HasValue, x => x.Grade >= dto.MinGrade)
                .WhereIF(dto.AiQuality.HasValue, x => x.AiQuality == dto.AiQuality)                           //质检方式
                .WhereIF(!string.IsNullOrEmpty(dto.Channel), x => x.Order.SourceChannelCode == dto.Channel)    //来源渠道
                .WhereIF(dto.AcceptanceTimeStart.HasValue, x => x.Order.CreationTime >= dto.AcceptanceTimeStart) //受理时间Star
                .WhereIF(dto.AcceptanceTimeEnd.HasValue, x => x.Order.CreationTime <= dto.AcceptanceTimeEnd)   //受理时间End
                .WhereIF(dto.Status.HasValue, x => x.Order.Status == dto.Status)                               //工单状态
                .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), x => x.Order.AcceptTypeCode == dto.AcceptTypeCode) //受理类型
                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), x => x.Order.HotspotSpliceName != null && x.Order.HotspotSpliceName.Contains(dto.Hotspot)) //热点
                .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), x => x.Order.AcceptorName == dto.NameOrNo! || x.Order.AcceptorStaffNo == dto.NameOrNo!)   //受理人/坐席
                .WhereIF(!string.IsNullOrEmpty(dto.FromPhone), x => x.Order.FromPhone.Contains(dto.FromPhone)) //来电号码
                .WhereIF(!string.IsNullOrEmpty(dto.UserName), x => x.UserName.Contains(dto.UserName))          //质检人
                .WhereIF(dto.QualityTimeStar.HasValue, x => x.QualityTime >= dto.QualityTimeStar)              //质检时间Star
                .WhereIF(dto.QualityTimeEnd.HasValue, x => x.QualityTime <= dto.QualityTimeEnd)                //质检时间End
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<QualityDto>(total, _mapper.Map<IReadOnlyList<QualityDto>>(items));
        }

        /// <summary>
        /// 获取质检实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<QualityDto> Entity(string id)
        {
            var quality = await _qualitey.Queryable()
                .Includes(x => x.Order)
                .Includes(x => x.Visit)
                .Includes(x => x.Visit, e => e.Employee)
                .Includes(x => x.QualityDetails)
                .FirstAsync(x => x.Id == id);
            var qualityDto = _mapper.Map<QualityDto>(quality);
            // if (qualityDto.Order != null) {
            //              //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
            //              var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
            //              if (call != null)
            //              {
            // 		qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
            // 		qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
            //              }
            // }
            // if (qualityDto.Visit != null)
            // {
            //              //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
            //              var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
            //              if (call != null)
            //              {
            //                  qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
            //                  qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
            //              }
            //          }

            if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
            {
                if (qualityDto.Order != null)
                {
                    //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Order.CallId).FirstAsync(); //由CallAccept改为OtherAccept
                    //var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Order.CallId).FirstAsync();
                    var call = await _callApplication.GetTianrunCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted);
                    if (call != null)
                    {
                        qualityDto.Order.RecordingBaseAddress = call.RecordingBaseAddress;
                        qualityDto.Order.RecordingAbsolutePath = call.RecordingAbsolutePath;
                    }
                }
                if (qualityDto.Visit != null)
                {
                    //var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == qualityDto.Visit.CallId).FirstAsync(); //由CallAccept改为OtherAccept
                    // var call = await _trCallRecordRepository.Queryable().Where(x => x.OtherAccept == qualityDto.Visit.CallId).FirstAsync();
                    var call = await _callApplication.GetTianrunCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
                    if (call != null)
                    {
                        qualityDto.Visit.RecordingBaseAddress = call.RecordingBaseAddress;
                        qualityDto.Visit.RecordingAbsolutePath = call.RecordingAbsolutePath;
                    }
                }
            }
            else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
            {
                if (!string.IsNullOrEmpty(qualityDto?.Order?.CallId))
                {
                    var call = await _callApplication.GetCallAsync(qualityDto.Order.CallId, HttpContext.RequestAborted);
                    if (call != null)
                    {
                        qualityDto.Order.RecordingBaseAddress = call.AudioFile;
                        qualityDto.Order.RecordingAbsolutePath = call.AudioFile;
                    }
                }
                if (!string.IsNullOrEmpty(qualityDto?.Visit?.CallId))
                {
                    var call = await _callApplication.GetCallAsync(qualityDto.Visit.CallId, HttpContext.RequestAborted);
                    if (call != null)
                    {
                        qualityDto.Visit.RecordingBaseAddress = call.AudioFile;
                        qualityDto.Visit.RecordingAbsolutePath = call.AudioFile;
                    }
                }
            }

            return qualityDto;
        }
        #endregion

        #region 质检项管理 
        /// <summary>
        /// 新增项目
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        [HttpPost("item")]
        public async Task Add([FromBody] QualityItemAddDto dto)
        {
            var count = await _qualiteyItem.CountAsync(x => x.Name == dto.Name);
            if (count > 0)
                throw UserFriendlyException.SameMessage("质检项目名称已存在");
            var model = _mapper.Map<QualityItem>(dto);
            await _qualiteyItem.AddAsync(model, HttpContext.RequestAborted);
        }

        ///// <summary>
        ///// 删除项目
        ///// </summary>
        ///// <param name="dto"></param>
        ///// <returns></returns>
        //[HttpDelete("item")]
        //public async Task Delete([FromBody] QualityItemDeleteDto dto)
        //{
        //	await _qualiteyItem.RemoveAsync(x => x.Id == dto.Id);
        //}

        /// <summary>
        /// 删除项目
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete("itemBatch")]
        public async Task Delete([FromBody] QualityItemBatchDeleteDto dto)
        {
            List<QualityItem> items = await _qualiteyItem.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
            foreach (var item in items)
            {
                var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name).AnyAsync();
                //质检中已存在不可以删
                if (detail) items.Remove(item);
            }
            if (items.Any())
            {
                await _qualiteyItem.RemoveRangeAsync(items, true, HttpContext.RequestAborted);
                var tempItems = await _qualiteyTemplateDetail.Queryable().In(x => x.ItemId, items.Select(x => x.Id)).ToListAsync(HttpContext.RequestAborted);
                if (tempItems.Any()) await _qualiteyTemplateDetail.RemoveRangeAsync(tempItems, HttpContext.RequestAborted);
            }
        }

        /// <summary>
        /// 更新项目
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("item")]
        public async Task Update([FromBody] QualityItemUpdateDto dto)
        {
            var item = await _qualiteyItem.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (item is null)
                throw UserFriendlyException.SameMessage("无效质检项目");
            if (item.IsEnable != dto.IsEnable || item.Name != dto.Name)
            {
                var detail = await _qualiteyDetail.Queryable().Where(x => x.Name == item.Name && !x.IsDeleted).AnyAsync();
                if (detail) throw UserFriendlyException.SameMessage("质检项目在中心质检中已使用,不能修改状态和名称！");
            }
            _mapper.Map(dto, item);
            item.LastModificationName = _sessionContext.UserName;
            await _qualiteyItem.UpdateAsync(item, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取项目列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("item/list")]
        public async Task<PagedDto<QualityItemDto>> List([FromQuery] QualityItemListDto dto)
        {
            var (total, items) = await _qualiteyItem.Queryable()
                .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
                .WhereIF(!string.IsNullOrEmpty(dto.GroupingName), d => d.GroupingName.Contains(dto.GroupingName!))
                .WhereIF(dto.IsEnable.HasValue, d => d.IsEnable == dto.IsEnable)

                .WhereIF(!string.IsNullOrEmpty(dto.Describe), d => d.Describe.Contains(dto.Describe!))
                .WhereIF(dto.MaxGrade.HasValue, d => d.Grade <= dto.MaxGrade)
                .WhereIF(dto.MinGrade.HasValue, d => d.Grade >= dto.MinGrade)
                .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), d => d.CreatorName.Contains(dto.CreatorName!))
                .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
                .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
                .WhereIF(!string.IsNullOrEmpty(dto.LastModificationName), d => d.LastModificationName.Contains(dto.LastModificationName!))
                .WhereIF(dto.LastModificationTimeStart.HasValue, d => d.LastModificationTime >= dto.LastModificationTimeStart)
                .WhereIF(dto.LastModificationTimeEnd.HasValue, d => d.LastModificationTime <= dto.LastModificationTimeEnd)
                .OrderByDescending(d => d.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<QualityItemDto>(total, _mapper.Map<IReadOnlyList<QualityItemDto>>(items));
        }

        /// <summary>
        /// 获取项目实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("item/{id}")]
        public async Task<QualityItem> ItemEntity(string id)
        {
            return await _qualiteyItem.Queryable()
                .FirstAsync(x => x.Id == id);
        }

        #endregion

        #region 质检模版管理
        /// <summary>
        /// 新增模版
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        [HttpPost("template")]
        public async Task Add([FromBody] TemplateAddDto dto)
        {
            var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.IsEnable == 1);
            if (groupingCount > 0 && dto.IsEnable == 1)
                throw UserFriendlyException.SameMessage("当前已存在");
            var names = dto.TemplateDetails.Select(x => x.ItemId).ToList();
            var nameCount = names.GroupBy(x => x).Count(c => c.Count() > 1);
            if (nameCount > 0)
                throw UserFriendlyException.SameMessage("质检模版存在重复质检项");
            var model = _mapper.Map<QualityTemplate>(dto);
            var id = await _qualityTemplate.AddAsync(model, HttpContext.RequestAborted);
            if (!string.IsNullOrEmpty(id))
            {
                foreach (var item in dto.TemplateDetails)
                {
                    item.TemplateId = id;
                }
                List<QualityTemplateDetail> details = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
                await _qualiteyTemplateDetail.AddRangeAsync(details, HttpContext.RequestAborted);
            }
        }

        /// <summary>
        /// 删除模版
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete("template")]
        public async Task Delete([FromBody] TemplateDeleteDto dto)
        {
            await _qualityTemplate.RemoveAsync(x => x.Id == dto.Id);
            List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
            await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除模版
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete("templateBatch")]
        public async Task Delete([FromBody] TemplateBatchDeleteDto dto)
        {
            List<QualityTemplate> templates = await _qualityTemplate.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
            List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().In(x => x.TemplateId, dto.Ids).ToListAsync();
            await _qualityTemplate.RemoveRangeAsync(templates, HttpContext.RequestAborted);
            await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 更新模版
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("template")]
        public async Task Update([FromBody] TemplateUpdateDto dto)
        {
            var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (template is null)
                throw UserFriendlyException.SameMessage("无效质检模版");
            var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
            if (groupingCount > 0)
                throw UserFriendlyException.SameMessage("当前质检分类已存在");
            _mapper.Map(dto, template);
            template.LastModificationName = _sessionContext.UserName;
            await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
            if (dto.TemplateDetails.Any())
            {
                List<QualityTemplateDetail> details = await _qualiteyTemplateDetail.Queryable().Where(x => x.TemplateId == dto.Id).ToListAsync();
                await _qualiteyTemplateDetail.RemoveRangeAsync(details, HttpContext.RequestAborted);
                foreach (var item in dto.TemplateDetails)
                {
                    item.TemplateId = dto.Id;
                }
                List<QualityTemplateDetail> newDetails = _mapper.Map<List<QualityTemplateDetail>>(dto.TemplateDetails);
                await _qualiteyTemplateDetail.AddRangeAsync(newDetails, HttpContext.RequestAborted);
            }
        }

        /// <summary>
        /// 获取模版列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("template/list")]
        public async Task<PagedDto<QualityTemplateDto>> List([FromQuery] TemplateListDto dto)
        {
            var (total, items) = await _qualityTemplate.Queryable()
                .Includes(x => x.templateDetails)
                .Includes(x => x.templateDetails, y => y.QualityItem)
                .WhereIF(!string.IsNullOrEmpty(dto.Name), x => x.Name.Contains(dto.Name!))
                .WhereIF(dto.Grouping.HasValue, x => x.Grouping == dto.Grouping)
                .WhereIF(dto.IsEnable.HasValue, x => x.IsEnable == dto.IsEnable)
                .WhereIF(!string.IsNullOrEmpty(dto.CreatorName), x => x.CreatorName.Contains(dto.CreatorName!))
                .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
                .WhereIF(!string.IsNullOrEmpty(dto.LastModificationName), x => x.LastModificationName.Contains(dto.LastModificationName!))
                .WhereIF(dto.LastModificationTimeStart.HasValue, x => x.LastModificationTime >= dto.LastModificationTimeStart)
                .WhereIF(dto.LastModificationTimeEnd.HasValue, x => x.LastModificationTime <= dto.LastModificationTimeEnd)
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<QualityTemplateDto>(total, _mapper.Map<IReadOnlyList<QualityTemplateDto>>(items));
        }

        /// <summary>
        /// 获取模版实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("template/{id}")]
        public async Task<QualityTemplateDto> TemplateEntity(string id)
        {
            var template = await _qualityTemplate.Queryable()
                .Includes(x => x.templateDetails)
                .Includes(x => x.templateDetails, y => y.QualityItem)
                .FirstAsync(x => x.Id == id);
            return _mapper.Map<QualityTemplateDto>(template);
        }
        /// <summary>
        /// 启禁用
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("template/enable")]
        public async Task Enable([FromBody] TemplateUpdateDto dto)
        {
            var template = await _qualityTemplate.GetAsync(dto.Id, HttpContext.RequestAborted);
            var groupingCount = await _qualityTemplate.CountAsync(x => x.Grouping == dto.Grouping && x.Id != dto.Id && x.IsEnable == 1);
            if (groupingCount > 0)
                throw UserFriendlyException.SameMessage("当前质检分类已存在");
            if (template is null)
                throw UserFriendlyException.SameMessage("无效质检模版");
            _mapper.Map(dto, template);
            await _qualityTemplate.UpdateAsync(template, HttpContext.RequestAborted);
        }
        #endregion

        #region 质检词库管理

        /// <summary>
        /// 新增违禁词
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
        [HttpPost("prohibited")]
        public async Task Add([FromBody] ProhibitedAddDto dto)
        {
            var model = _mapper.Map<QualityProhibited>(dto);
            await _qualiteyProhibited.AddAsync(model, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除违禁词
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete("prohibited")]
        public async Task Delete([FromBody] ProhibitedDeleteDto dto)
        {
            await _qualiteyProhibited.RemoveAsync(x => x.Id == dto.Id);
        }

        /// <summary>
        /// 删除违禁词
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpDelete("prohibitedBatch")]
        public async Task Delete([FromBody] ProhibitedBatchDeleteDto dto)
        {
            List<QualityProhibited> prohibiteds = await _qualiteyProhibited.Queryable().In(x => x.Id, dto.Ids).ToListAsync();
            await _qualiteyProhibited.RemoveRangeAsync(prohibiteds, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 更新违禁词
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("prohibited")]
        public async Task Update([FromBody] ProhibitedUpdateDto dto)
        {
            var prohibited = await _qualiteyProhibited.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (prohibited is null)
                throw UserFriendlyException.SameMessage("无效质检模版");
            _mapper.Map(dto, prohibited);
            prohibited.LastModificationName = _sessionContext.UserName;
            await _qualiteyProhibited.UpdateAsync(prohibited, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 获取违禁词列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("prohibited/list")]
        public async Task<PagedDto<QualityProhibitedDto>> List([FromQuery] ProhibitedListDto dto)
        {
            var (total, items) = await _qualiteyProhibited.Queryable()
                .WhereIF(!string.IsNullOrEmpty(dto.Name), d => d.Name.Contains(dto.Name!))
                .WhereIF(!string.IsNullOrEmpty(dto.Classify), d => d.Classify.Contains(dto.Classify!))
                .WhereIF(!string.IsNullOrEmpty(dto.Type), d => d.Type.Contains(dto.Type!))
                .OrderByDescending(x => x.CreationTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<QualityProhibitedDto>(total, _mapper.Map<IReadOnlyList<QualityProhibitedDto>>(items));
        }

        /// <summary>
        /// 获取违禁词实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("prohibited/{id}")]
        public async Task<QualityProhibited> ProhibitedEntity(string id)
        {
            return await _qualiteyProhibited.Queryable()
                .FirstAsync(x => x.Id == id);
        }
        #endregion

        /// <summary>
        /// 获取质检基本信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("base")]
        public async Task<object> Base()
        {
            var rsp = new
            {
                QualityState = EnumExts.GetDescriptions<EQualityState>(),
                QualitySource = EnumExts.GetDescriptions<EQualitySource>()
            };
            return rsp;
        }

        /// <summary>
        /// 获取质检项目基本信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("item_base")]
        public async Task<object> ItemBase()
        {
            var rsp = new
            {
                QualityItemGrouping = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.QualityItemGrouping)
            };
            return rsp;
        }

        /// <summary>
        /// 获取质检模版基本信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("template_base")]
        public async Task<object> TemplateBase()
        {
            var rsp = new
            {
                TemplateGrouping = EnumExts.GetDescriptions<ETemplateGrouping>()
            };
            return rsp;
        }

        /// <summary>
        /// 获取质检违禁词基本信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("prohibited_base")]
        public async Task<object> ProhibitedBase()
        {
            var rsp = new
            {
                ProhibitedClassify = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedClassify),
                ProhibitedType = _systemDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.ProhibitedType),
            };
            return rsp;
        }

        /// <summary>
        /// 智能质检转写_兴唐
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("aitransfer_xt")]
        [LogFilter("智能质检转写_兴唐")]
        public async Task AiTransfer_XT([FromBody] List<AiQualityXTDto> dto)
        {
            var transfers = new List<QualityTransferRecords>();
            foreach (var item in dto)
            {
                var records = await _qualityTransferRecordsRepository.Queryable().Where(x => x.QualityId == item.Id && x.IsFinished == false).AnyAsync();
                if (records)
                    continue;

                var transfer = new QualityTransferRecords();
                transfer.QualityId = item.Id;
                transfer.IsFinished = false;
                transfer.TransferState = EQualityTransferState.NotStarted;
                transfers.Add(transfer);
                await _qualitey.Updateable().SetColumns(x => new Hotline.Quality.Quality { TransferState = EQualityTransferState.Translating }).Where(x => x.Id == item.Id).ExecuteCommandAsync();
            }
            await _qualityTransferRecordsRepository.AddRangeAsync(transfers);
        }

        /// <summary>
        /// 智能质检转写_兴唐_定时调用
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("transfer")]
        [LogFilter("智能质检转写_兴唐_定时调用")]
        public async Task AiTransfer_XT()
        {
            var translatings = await _qualityTransferRecordsRepository.Queryable().Where(x => x.IsFinished == false && x.TransferState == EQualityTransferState.Translating).OrderBy(x => x.TransferTime).ToListAsync();
            if (translatings.Any())
            {
                var transfer = translatings.FirstOrDefault();
                if ((DateTime.Now - transfer.TransferTime.Value).TotalMinutes >= 30)
                {
                    await _qualityTransferRecordsRepository.Updateable().SetColumns(x => new QualityTransferRecords { TransferState = EQualityTransferState.Lose }).Where(x => x.Id == transfer.Id).ExecuteCommandAsync();
                    await _qualitey.Updateable().SetColumns(x => new Hotline.Quality.Quality { TransferState = EQualityTransferState.Lose }).Where(x => x.Id == transfer.QualityId).ExecuteCommandAsync();
                }
                return;
            }
            else
            {
                var trany = await _qualityTransferRecordsRepository.Queryable().Where(x => x.IsFinished == false && x.TransferState == EQualityTransferState.NotStarted).AnyAsync();
                if (trany)
                {
                    var notStarted = await _qualityTransferRecordsRepository.Queryable().Where(x => x.IsFinished == false && x.TransferState == EQualityTransferState.NotStarted).OrderBy(x => x.TransferTime).FirstAsync();
                    await _qualityTransferRecordsRepository.Updateable().SetColumns(x => new QualityTransferRecords { TransferState = EQualityTransferState.Translating, TransferTime = DateTime.Now }).Where(x => x.Id == notStarted.Id).ExecuteCommandAsync();
                    Task.Run(async () => await _qualityApplication.Transfer_XT(notStarted.QualityId, HttpContext.RequestAborted));
                }
            }
        }


        /// <summary>
        /// 智能质检结果返回接收 
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("AiResult")]
        [LogFilter("智能质检结果返回接收")]
        public async Task AiResult([FromBody] List<AiQualityResultDto> dto)
        {
            //Request.EnableBuffering();
            //var sr = new StreamReader(Request.Body);
            //var data = await sr.ReadToEndAsync(HttpContext.RequestAborted);
            //   _logger.LogInformation(data);
            //   await _logRepository.Updateable().SetColumns( x=> new SystemLog(){ ExecuteParam = data }).Where(x => x.Id == "08dcb132-cf60-4d1f-84ae-eb0c463f2175").ExecuteCommandAsync();

            await _qualityApplication.AiResultAsync(dto, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 重推质检 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("AiResultTest/{id}")]
        public async Task TaskAsync(string id)
        {
            var quality = await _qualitey.GetAsync(id, HttpContext.RequestAborted);
            var order = await _orderRepository.GetAsync(quality.OrderId, HttpContext.RequestAborted);
            if (order != null && !string.IsNullOrEmpty(order.CallId))
            {
                quality.AiQuality = true;
                //var call = await _trCallRecordRepository.GetAsync(x => x.CallAccept == order.CallId, HttpContext.RequestAborted); //由CallAccept改为OtherAccept
                //var call = await _trCallRecordRepository.GetAsync(x => x.OtherAccept == order.CallId, HttpContext.RequestAborted);

                var audioFile = string.Empty;
                var fromNo = string.Empty;
                DateTime? callStartTime = null;
                if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.TianRun)
                {
                    var call = await _callApplication.GetTianrunCallAsync(order.CallId, HttpContext.RequestAborted);
                    audioFile = call.RecordingAbsolutePath;
                    fromNo = call.CPN;
                    callStartTime = call.CreatedTime;
                }
                else if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XingTang)
                {
                    var call = await _callApplication.GetCallAsync(order.CallId, HttpContext.RequestAborted);
                    audioFile = call.AudioFile;
                    fromNo = call.FromNo;
                    callStartTime = call.BeginIvrTime;
                }
                if (_appOptions.Value.IsYiBin)
                {
                    var aiQualityService = _serviceProvider.GetRequiredService<IAiQualityService>();
                    var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);
                    try
                    {
                        await aiQualityService.CreateAiOrderQualityTask(
                              quality.Id,
                              audioFile,
                              fromNo,
                              callStartTime,
                              setting?.SettingValue[0], quality.Source.ToString(), HttpContext.RequestAborted);
                    }
                    catch (Exception e)
                    {
                        _logger.LogError($"写入智能质检异常3！, \r\n{e.Message}");
                    }
                }
                await _qualitey.UpdateAsync(quality, HttpContext.RequestAborted);
            }
        }

    }
}
