using Hotline.Application.CallCenter;
using Hotline.Share.Tools;
using Hotline.Caching.Interfaces;
using Hotline.CallCenter.BlackLists;
using Hotline.CallCenter.Calls;
using Hotline.CallCenter.Configs;
using Hotline.CallCenter.Tels;
using Hotline.EventBus;
using Hotline.Quality.Notifications;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Dtos.Quality;
using Hotline.Share.Dtos.TrCallCenter;
using Hotline.Share.Enums.CallCenter;
using Hotline.Repository.SqlSugar.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Threading;
using XF.Domain.Exceptions;
using XF.Utility.EnumExtensions;
using XF.Domain.Repository;
using MapsterMapper;
using SqlSugar;
using Hotline.Api.Filter;
using Microsoft.AspNetCore.Authorization;
using Hotline.Share.Dtos.Order;
using Hotline.Tools;
using XF.Domain.Authentications;

namespace Hotline.Api.Controllers
{
    public class CallController : BaseController
    {
        private readonly ICallApplication _callApplication;
        private readonly Publisher _publisher;
        private readonly IMapper _mapper;
        private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly IRepository<TelOperationXthx> _telOperationXthxRepository;

        public CallController(
            ICallApplication callApplication,
            Publisher publisher,
            IMapper mapper,
            IOptionsSnapshot<CallCenterConfiguration> callcenterOptions,
            ISystemSettingCacheManager systemSettingCacheManager,
            IRepository<TelOperationXthx> telOperationXthxRepository)
        {
            _callApplication = callApplication;
            _publisher = publisher;
            _mapper = mapper;
            _callcenterOptions = callcenterOptions;
            _systemSettingCacheManager = systemSettingCacheManager;
            _telOperationXthxRepository = telOperationXthxRepository;
        }

        /// <summary>
        /// 查询分机组和分机
        /// </summary>
        [HttpGet("querygrouptel")]
        public Task<IReadOnlyList<TelGroupDto>> QueryGroupTel()
            => _callApplication.QueryGroupTel(HttpContext.RequestAborted);

        /// <summary>
        /// 查询分机
        /// </summary>
        [HttpGet("tels")]
        public async Task<IList<TelDto>> QueryTels()
            => (await _callApplication.QueryTelsAsync(new QueryTelsInDto(null) { PageSize = 99999 }, HttpContext.RequestAborted)).Item2;

        /// <summary>
        /// 查询分机
        /// </summary>
        [HttpGet("tels-paged")]
        public async Task<PagedDto<TelDto>> QueryTelsAsync([FromQuery] QueryTelsInDto dto)
            => (await _callApplication.QueryTelsAsync(dto, HttpContext.RequestAborted)).ToPaged();

        /// <summary>
        /// 查询分机组
        /// </summary>
        [HttpGet("groups")]
        public Task<IReadOnlyList<TelGroupDto>> QueryTelGroups()
            => _callApplication.QueryTelGroupsAsync(HttpContext.RequestAborted);

        #region 黑名单

        //Task<string> AddBlackListAsync(AddBlacklistDto dto, CancellationToken cancellationToken);
        //Task RemoveBlackListAsync(string id, CancellationToken cancellationToken);
        //Task<List<Blacklist>> QueryBlackListsAsync(CancellationToken cancellationToken);

        #endregion

        /// <summary>
        /// 签入
        /// </summary>
        [HttpPost("signin")]
        [LogFilter("分机签入")]
        public Task<TrOnDutyResponseDto> SignIn([FromBody] SignInDto dto)
            => _callApplication.SignInAsync(dto, HttpContext.RequestAborted);

        /// <summary>
        /// 签出
        /// </summary>
        [HttpPost("signout")]
        [LogFilter("分机签出")]
        public Task SignOut()
            => _callApplication.SingOutAsync(HttpContext.RequestAborted);

        /// <summary>
        /// 签出
        /// </summary>
        [HttpPost("signout/{telNo}")]
        [LogFilter("分机签出")]
        public Task SignOut(string telNo)
            => _callApplication.SingOutAsync(telNo, HttpContext.RequestAborted);

        /// <summary>
        /// 查询当前用户的分机状态
        /// </summary>
        /// <returns></returns>
        [HttpGet("tel-state")]
        public Task<TrOnDutyResponseDto> GetTelState()
            => _callApplication.GetTelStateAsync(HttpContext.RequestAborted);

        /// <summary>
        /// 查询通话记录（固定数据量）
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("calls-fixed")]
        public async Task<List<CallNativeDto>> QueryCallsFixed([FromQuery] QueryCallsFixedDto dto)
            => await _callApplication.QueryCallsFixedAsync(dto, HttpContext.RequestAborted).ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);

        /// <summary>
        /// 查询通话记录（固定数据量）
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("calls-fixed/count")]
        public async Task<int> QueryCallsFixedCount([FromQuery] QueryCallsFixedDto dto)
            => await _callApplication.QueryCallsFixedAsync(dto, HttpContext.RequestAborted).CountAsync(HttpContext.RequestAborted);

		/// <summary>
		/// 导出通话记录
		/// </summary>
		/// <param name="dto"></param>
		/// <returns></returns>
		[HttpPost("calls-fixed/export")]
		[LogFilterAlpha("导出日志")]
		public async Task<FileStreamResult> ExportOrders([FromBody] ExportExcelDto<QueryCallsFixedDto> dto)
		{
			var query = _callApplication.QueryCallsFixedAsync(dto.QueryDto, HttpContext.RequestAborted);
			List<CallNativeDto> callls;
			if (dto.IsExportAll)
			{
				callls = await query.ToListAsync(HttpContext.RequestAborted);
			}
			else
			{
				var (_, items) = await query.ToPagedListAsync(dto.QueryDto, HttpContext.RequestAborted);
				callls = items;
			}
			dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<CallNativeDto>(dto.ColumnInfos);

			var dtos = callls
				.Select(stu => _mapper.Map(stu, typeof(CallNativeDto), dynamicClass))
				.Cast<object>()
				.ToList();

			var stream = ExcelHelper.CreateStream(dtos);

			return ExcelStreamResult(stream, "通话记录");
		}

		/// <summary>
		/// 查询通话记录
		/// </summary>
		/// <param name="callId"></param>
		/// <returns></returns>
		[HttpGet("{callId}")]
        public Task<List<CallNative>> GetCall(string callId)
        {
            //为兼容天润通话记录返回集合
            if (string.IsNullOrEmpty(callId)) return default;
            return _callApplication.GetCallListAsync(callId, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 通话记录基础数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("base-data")]
        public object BaseData()
        {
            return new
            {
                Direction = EnumExts.GetDescriptions<ECallDirection>(),
                EndBy = EnumExts.GetDescriptions<EEndBy>(),
            };
        }

        /// <summary>
        /// 查询坐席操作记录(固定数据量)
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("tel-operations-fixed")]
        public async Task<IReadOnlyList<TelOperation>> QueryTelOperationsAsync([FromQuery] QueryTelOperationsFixedDto dto) =>
            await _callApplication.QueryTelOperationsAsync(dto).ToPageListWithoutTotalAsync(dto, HttpContext.RequestAborted);

        /// <summary>
        /// 查询坐席操作记录(固定数据量)
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("tel-operations-fixed/count")]
        public async Task<int> QueryTelOperationsCountAsync([FromQuery] QueryTelOperationsFixedDto dto) =>
            await _callApplication.QueryTelOperationsAsync(dto).CountAsync(HttpContext.RequestAborted);

        /// <summary>
        /// 查询坐席操作记录基础数据
        /// </summary>
        [HttpGet("base-data-tel-operation")]
        public object BaseDataTelOperation()
        {
            return new
            {
                Operations = _callApplication.GetTelOperationOptions()
            };
        }

        /// <summary>
        /// 通话转写
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("calls/transliteration")]
        public async Task CallTransliteration([FromBody] CallTransliteration dto)
        {
            foreach (var id in dto.Ids)
            {
                var call = await _callApplication.GetTianrunCallAsync(id, HttpContext.RequestAborted);
                if (call is null)
                    throw UserFriendlyException.SameMessage("通话信息错误");
                if (call.TransliterationState == ECallTransliterationState.Underway)
                    throw UserFriendlyException.SameMessage("正在转写中,请勿重复点击，请稍作等待");
                if (call.TransliterationState == ECallTransliterationState.Succeed)
                    throw UserFriendlyException.SameMessage("转写成功，不能重新转写");
                call.InitTransliterationId();
                await _callApplication.EditTransliterationStateAsync(call.Id, ECallTransliterationState.Underway, call.TransliterationId, HttpContext.RequestAborted);
                var audioFile = call.RecordingAbsolutePath;
                var fromNo = call.CPN;
                var callStartTime = call.CreatedTime;
                var Id = call.TransliterationId;
                var setting = _systemSettingCacheManager.GetSetting(SettingConstants.ViteRecordPrefix);



                var handler = new AiQualityHandler()
                {
                    Id = Id,
                    Source = "AiAnswered",
                    AudioFile = audioFile,
                    FromNo = fromNo,
                    CallStartTime = callStartTime,
                    ViteRecordPrefix = setting?.SettingValue[0],
                };
                await _publisher.PublishAsync(new AiOrderQualityNotify(handler), PublishStrategy.ParallelNoWait, HttpContext.RequestAborted);
            }
        }

        #region 坐席动作类型统计

        /// <summary>
        /// 坐席动作类型统计
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpGet("telaction/list")]
        public async Task<PagedDto<TelActionListXthx>> TelActionList([FromQuery] TelActionXthxDto dto)
        {
            var (total, items) = await _telOperationXthxRepository.Queryable()
                .WhereIF(string.IsNullOrEmpty(dto.TelNo) == false, x => x.TelNo.Contains(dto.TelNo))
                .WhereIF(dto.OperationStatus != null, x => x.OperationStatus == dto.OperationStatus)
                .WhereIF(string.IsNullOrEmpty(dto.UserName) == false, x => x.UserName.Contains(dto.UserName))
                .WhereIF(dto.StartTime.HasValue, x => x.StartTime >= dto.StartTime)
                .WhereIF(dto.EndTime.HasValue, x => x.StartTime <= dto.EndTime)
                .OrderByDescending(x => x.StartTime)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
            return new PagedDto<TelActionListXthx>(total, _mapper.Map<IReadOnlyList<TelActionListXthx>>(items));
        }

        #endregion
    }
}
