using Hotline.Api.Filter;
using Hotline.Caching.Interfaces;
using Hotline.Caching.Services;
using Hotline.CallCenter.Manage;
using Hotline.Orders;
using Hotline.Permissions;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.Repository.SqlSugar.Ts;
using Hotline.Settings;
using Hotline.Settings.TimeLimits;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.Settings;
using Hotline.Share.Enums.Settings;
using Hotline.Share.Requests;
using MapsterMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using XF.Utility.EnumExtensions;

namespace Hotline.Api.Controllers
{
    /// <summary>
    /// 系统参数相关接口
    /// </summary>
    public class SettingController : BaseController
    {
        private readonly IVoiceFileDomainService _voiceFileDomainService;
        private readonly IRepository<SystemSetting> _systemSettingsRepository;
        private readonly ISystemSettingCacheManager _systemSettingCacheManager;
        private readonly IDaySettingRepository _daysettingRepository;
        private readonly IMapper _mapper;
        private readonly IBusinessTagRepository _businessTag;
        private readonly IRepositoryTextSearch<OrderTs> _repositoryts;
        private readonly IDaySettingCacheManager _daySettingCacheManager;

        public SettingController(
            IVoiceFileDomainService voiceFileDomainService,
            IRepository<SystemSetting> systemSettingsRepository,
            ISystemSettingCacheManager systemSettingCacheManager,
            IDaySettingRepository daySettingRepository,
            IMapper mapper,
            IBusinessTagRepository businessTag,
            IRepositoryTextSearch<OrderTs> repositoryts,
            IDaySettingCacheManager daySettingCacheManager)
        {
            _voiceFileDomainService = voiceFileDomainService;
            _systemSettingsRepository = systemSettingsRepository;
            _systemSettingCacheManager = systemSettingCacheManager;
            _daysettingRepository = daySettingRepository;
            _mapper = mapper;
            _businessTag = businessTag;
            _repositoryts = repositoryts;
            _daySettingCacheManager = daySettingCacheManager;
        }

        /// <summary>
        /// 查询语音文件
        /// </summary>
        /// <returns></returns>
        [HttpGet("voicequerylist")]
        public async Task<List<string>> VoiceQueryList()
        {
            return await _voiceFileDomainService.VoiceQueryListAsync(HttpContext.RequestAborted);
        }

        /// <summary>
        /// 删除语音文件
        /// </summary>
        /// <param name="voiceFileName"></param>
        /// <returns></returns>
        [HttpPost("removevoicefile")]
        public async Task RemoveVoiceFile(string voiceFileName)
        {
            await _voiceFileDomainService.RemoveVoiceFileAsync(new RemoveVoiceFileRequest(voiceFileName), HttpContext.RequestAborted);
        }

        #region 系统参数
        /// <summary>
        /// 获取系统参数列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("getsyssettings")]
        public async Task<PagedDto<SystemSetting>> GetSysSettings([FromQuery]SettingsQueryDto dto)
        {
            //return await _systemSettingsRepository.QueryAsync(x => true);

            var (total,items) = await _systemSettingsRepository.Queryable()
                .Includes(d=>d.Creator)
                .WhereIF(!string.IsNullOrEmpty(dto.settingName), d => d.SettingName.Contains(dto.settingName))
                .WhereIF(!string.IsNullOrEmpty(dto.code),d=>d.Code.Contains(dto.code))
                .OrderBy(d=>d.CreationTime)
                .OrderBy(d => d.Sort)
                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);

            return new PagedDto<SystemSetting>(total, items);
        }

        /// <summary>
        /// 获取系统参数
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("getsetting-entity/{id}")]
        public async Task<SystemSetting?> GetSettingEntity(string id)
        {
            return await _systemSettingsRepository.GetAsync(id, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 通过code获取系统参数
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("getsetting-code/{code}")]
        public async Task<SystemSetting?> GetSettingByCode(string code)
        {
            return  _systemSettingCacheManager.GetSetting(code);
        }


        /// <summary>
        /// 新增系统参数
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("setting-add")]
        public async Task AddSetting([FromBody]AddSettingDto dto)
        {
            var setting = _mapper.Map<SystemSetting>(dto);
            await _systemSettingsRepository.AddAsync(setting, HttpContext.RequestAborted);
        }

        /// <summary>
        /// 修改配置
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("modifysettings")]
        [LogFilter("修改系统配置")]
        public async Task ModifySettingsAsync([FromBody]ModifySettingDto  dto)
        {
            var model = await _systemSettingsRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
            if (model is null)
                throw UserFriendlyException.SameMessage("未知配置，请刷新界面");

            model.SettingValue = dto.SettingValue;
            model.Sort = dto.Sort;
            model.Remark = dto.Remark;
            _systemSettingCacheManager.DelSystemSetting(model.Code);
            await _systemSettingsRepository.UpdateAsync(model, HttpContext.RequestAborted);
        }

        #endregion

        #region 日期类型设置

        /// <summary>
        /// 获取月份的日期设置
        /// </summary>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <returns></returns>
        [HttpGet("getdaysettings-month/{year}/{month}")]
        public async Task<List<DaySetting>> GetDaySettingsByMonth(int year,int month)
        {
            return await _daysettingRepository.GetDaySettingsByMonth(year,month);
        }

        /// <summary>
        /// 设置日期
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>`
        [HttpPost("setdaysettings")]
        public async Task SetDaySettings([FromBody]SetDaySettingsRequest request)
        {
            _daySettingCacheManager.DelDaySetting();
            foreach (var item in request.list)
            {
                var day = await _daysettingRepository.GetAsync(x => x.Day.Date == item.Date, HttpContext.RequestAborted);
                if (day != null)
                {
                    day.IsWorkDay = request.isWorkDay;
                    await _daysettingRepository.UpdateAsync(day, HttpContext.RequestAborted);
                }
                else
                {
                    await _daysettingRepository.AddAsync(new DaySetting() { Day = item, IsWorkDay = request.isWorkDay },HttpContext.RequestAborted);
                }
            }
        }

        #endregion

        #region 标签

        /// <summary>
        /// 业务标签列表
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
		[HttpGet("businessTag")]
		public async Task<PagedDto<BusinessTagListVo>> BusinessTagList([FromQuery] BusinessTagListDto dto)
		{
			var (total, items) = await _businessTag.Queryable()
				.WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Name.Contains(dto.Keyword!))
				.WhereIF(dto.Type> 0, d => d.Type == dto.Type)
				.WhereIF(dto.BusinessType > 0, d => d.BusinessType == dto.BusinessType)
				.OrderByDescending(x => x.CreationTime)
				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
			return new PagedDto<BusinessTagListVo>(total, _mapper.Map<IReadOnlyList<BusinessTagListVo>>(items));
		}

        /// <summary>
        /// 新增标签(支持批量)
        /// </summary>
        /// <param name="dtos"></param>
        /// <returns></returns>
		[HttpPost("businessTag")]
		public async Task AddBusinessTag([FromBody] List<BusinessTagDto> dtos)
		{
			List<BusinessTag> tags = new List<BusinessTag>();
			foreach (var dto in dtos)
			{
				var model = _mapper.Map<BusinessTag>(dto);
				tags.Add(model);
			}
			await _businessTag.AddRangeAsync(tags, HttpContext.RequestAborted);
		}

        /// <summary>
        /// 删除标签
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
		[HttpDelete("businessTag")]
		public async Task DeleteBusinessTag([FromBody] DeleteBusinessTagDto dto)
		{
			foreach (var Id in dto.Ids)
			{
				await _businessTag.RemoveAsync(x => x.Id == Id);
			}
		}

        /// <summary>
        /// 更新标签
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
		[HttpPut("businessTag")]
		public async Task UpdateBusinessTag([FromBody] UpdateBusinessTagDto dto)
		{
			//验证工单是否可以申请
			var tag = await _businessTag.GetAsync(dto.Id, HttpContext.RequestAborted);
			if (tag is null)
				throw UserFriendlyException.SameMessage("无效标签");
			_mapper.Map(dto, tag);
			await _businessTag.UpdateAsync(tag, HttpContext.RequestAborted);
		}

        /// <summary>
        /// 获取标签实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
		[HttpGet("businessTag/{id}")]
		public async Task<BusinessTag> BusinessTagEntity(string id)
		{
			return await _businessTag.Queryable()
				.FirstAsync(x => x.Id == id);
		}

		/// <summary>
		/// 获取标签基本数据
		/// </summary>
		/// <returns></returns>
		[HttpGet("businessTag/baseData")]
		public async Task<object> TagBaseData()
		{
			var rsp = new
			{
				TagType = EnumExts.GetDescriptions<ETagType>(),
				BusinessTagType = EnumExts.GetDescriptions<EBusinessTagType>(),
			};
			return rsp;
		}

        /// <summary>
        /// 绑定标签
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPut("businessTag/binding")]
        public async Task BusinessTagBinding([FromBody]BusinessTagBindingDto dto)
        {
           await _businessTag.BindingAsync(dto, HttpContext.RequestAborted);
        }

        #endregion
    }
}
