using Hotline.CallCenter.Ivrs;
using Hotline.Permissions;
using Hotline.Share.Dtos.CallCenter;
using Hotline.Share.Enums.CallCenter;
using MapsterMapper;
using Microsoft.AspNetCore.Mvc;
using XF.Domain.Cache;
using XF.Domain.Exceptions;
using XF.Utility.EnumExtensions;

namespace Hotline.Api.Controllers;

/// <summary>
/// IVR相关接口管理
/// </summary>
public class IvrController : BaseController
{
    private readonly IIvrDomainService _ivrDomainService;
    private readonly IIvrRepository _ivrRepository;
    private readonly IIvrCategoryRepository _ivrCategoryRepository;
    private readonly ITypedCache<IReadOnlyList<Ivr>> _cacheIvrList;
    private readonly IMapper _mapper;

    public IvrController(
        IIvrDomainService ivrDomainService,
        IIvrRepository ivrRepository,
        IIvrCategoryRepository ivrCategoryRepository,
        ITypedCache<IReadOnlyList<Ivr>> cacheIvrList,
        IMapper mapper)
    {
        _ivrDomainService = ivrDomainService;
        _ivrRepository = ivrRepository;
        _ivrCategoryRepository = ivrCategoryRepository;
        _cacheIvrList = cacheIvrList;
        _mapper = mapper;
    }

    /// <summary>
    /// 查询所有ivr分类
    /// </summary>
    /// <returns></returns>
    [HttpGet("categories")]
    public async Task<IReadOnlyList<IvrCategory>> GetCategories()
    {
        return await _ivrCategoryRepository.QueryExtAsync(d => true, d => d.Includes(x => x.Ivrs));
    }

    /// <summary>
    /// 查询ivr分类（含ivr）
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("category/{id}")]
    public async Task<IvrCategory> GetCategory(string id)
    {
        return await _ivrCategoryRepository.GetExtAsync(d => d.Id == id, d => d.Includes(x => x.Ivrs));
    }

    /// <summary>
    /// 新增IVR分类
    /// </summary>
    /// <returns></returns>
    
    [HttpPost("category")]
    public async Task<string> AddCategory([FromBody] AddIvrCategoryDto request)
    {
        var category = _mapper.Map<IvrCategory>(request);
        return await _ivrCategoryRepository.AddAsync(category, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 更新IVR分类
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPut("category")]
    public async Task UpdateCategory([FromBody] UpdateIvrCategoryDto request)
    {
        var category = _mapper.Map<IvrCategory>(request);
        await _ivrCategoryRepository.UpdateAsync(category, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 删除分类，含分类下所有IVR
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("category/{id}")]
    public async Task RemoveCategory(string id)
    {
        var category = await _ivrCategoryRepository.GetExtAsync(d => d.Id == id, d => d.Includes(x => x.Ivrs));
        await _ivrRepository.RemoveRangeAsync(category.Ivrs, HttpContext.RequestAborted);
        await _ivrCategoryRepository.RemoveAsync(category);
        _cacheIvrList.Remove(Ivr.Key);
    }

    /// <summary>
    /// 新增IVR
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<string> Add([FromBody] AddIvrDto dto)
    {
        var ivr = _mapper.Map<Ivr>(dto);
        return await _ivrDomainService.AddIvrAsync(ivr, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 更新IVR
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPut]
    public async Task Update([FromBody] UpdateIvrDto dto)
    {
        var ivr = await _ivrRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
        _mapper.Map(dto, ivr);
        await _ivrDomainService.UpdateIvrAsync(ivr, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 构建IVR关系
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="UserFriendlyException"></exception>
    [HttpPost("structure")]
    public async Task Structure([FromBody] StructureIvrDto dto)
    {
        await _ivrDomainService.StructureIvrAsync(dto, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 删除IVR关系（并非删除IVR）
    /// </summary>
    /// <param name="ivrId"></param>
    /// <returns></returns>
    [HttpPut("destructure/{ivrId}")]
    public async Task DeStructureIvr(string ivrId)
    {
        await _ivrDomainService.DeStructureIvrAsync(ivrId, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 替换某个IVR分组下的起始IVR(根节点)
    /// </summary>
    /// <param name="ivrId"></param>
    /// <returns></returns>
    [HttpPut("replace-root/{ivrId}")]
    public async Task ReplaceRootAsync(string ivrId)
    {
        await _ivrDomainService.ReplaceRootAsync(ivrId, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 查询所有ivr
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<IReadOnlyList<IvrDto>> QueryIvrs()
    {
        var ivrs = await _ivrRepository.QueryAsync();
        return _mapper.Map<IReadOnlyList<IvrDto>>(ivrs);
    }

    /// <summary>
    /// 查询ivr分类，以树形结构返回IVR关系
    /// </summary>
    /// <param name="categoryId"></param>
    /// <returns></returns>
    [HttpGet("tree/{categoryId}")]
    public async Task<IvrDto> GetBeginingIvrAsync(string categoryId)
    {
        ////todo 1.
        ////超过1个根节点则视为未配置完成
        //var count = await _ivrRepository.CountAsync(
        //    d => d.IvrCategoryId == categoryId && string.IsNullOrEmpty(d.PrevIvrNo), HttpContext.RequestAborted);
        //if (count > 1)
        //    return null;
        var ivrs = await _ivrRepository.QueryAsync(d => d.IvrCategoryId == categoryId);
        var rootIvr = ivrs.FirstOrDefault(d => d.IsRoot);
        if (rootIvr == null)
            throw UserFriendlyException.SameMessage("每个IVR分类至少存在一个根节点");
        var rootDto = _mapper.Map<IvrDto>(rootIvr);
        BuildIvrTree(ivrs, rootDto);
        return rootDto;
    }

    /// <summary>
    /// 页面基础信息
    /// </summary>
    /// <returns></returns>
    [HttpGet("base-info")]
    public async Task<dynamic> GetBaseInfo()
    {
        return new
        {
            IvrTypes = EnumExts.GetDescriptions<EIvrType>(),
            IvrStrategeTypes = EnumExts.GetDescriptions<EIvrStrategeType>(),
            IvrAnswerTypes = EnumExts.GetDescriptions<EIvrAnswerType>(),
        };
    }

    private void BuildIvrTree(List<Ivr> ivrs, IvrDto dto)
    {
        var children = ivrs.Where(d => d.PrevIvrNo == dto.No && !d.IsRoot).ToList();
        if (!children.Any()) return;
        dto.ChildIvrs = _mapper.Map<IReadOnlyList<IvrDto>>(children);
        foreach (var dtoChildIvr in dto.ChildIvrs)
        {
            BuildIvrTree(ivrs, dtoChildIvr);
        }
    }
}