using Hotline.CallCenter.Devices;
using Hotline.Realtimes;
using Hotline.Users;
using System.Reflection;
using Hotline.FlowEngine;
using XF.Domain.Constants;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using Hotline.Share.Enums.CallCenter;
using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Configs;
using Microsoft.Extensions.Options;
using Hotline.Share.Dtos.CallCenter;
using Microsoft.Extensions.DependencyInjection;
using Hotline.Configurations;

namespace Hotline.CallCenter.Tels;

public class TelDomainService : ITelDomainService, IScopeDependency
{
    private readonly INewRockDeviceManager _newRockDeviceManager;
    private readonly ITelRepository _telRepository;
    private readonly ITelRestRepository _telRestRepository;
    private readonly ITelHoldRepository _telHoldRepository;
    private readonly IRealtimeService _realtimeService;
    private readonly ITelCacheManager _telCacheManager;
    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
    private readonly IOptionsSnapshot<CallCenterConfiguration> _callcenterOptions;
    private readonly string _callcenterType;

    public TelDomainService(
        IServiceProvider serviceProvider,
        ITelRepository telRepository,
        ITelRestRepository telRestRepository,
        ITelHoldRepository telHoldRepository,
        IRealtimeService realtimeService,
        ITelCacheManager telCacheManager,
        IOptionsSnapshot<AppConfiguration> appOptions,
        IOptionsSnapshot<CallCenterConfiguration> callcenterOptions)
    {
        _telRepository = telRepository;
        _telRestRepository = telRestRepository;
        _telHoldRepository = telHoldRepository;
        _realtimeService = realtimeService;
        _telCacheManager = telCacheManager;
        _appOptions = appOptions;
        _callcenterOptions = callcenterOptions;
        _callcenterType = appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType;
        if (_callcenterType == AppDefaults.CallCenterType.XunShi)
        {
            _newRockDeviceManager = serviceProvider.GetRequiredService<INewRockDeviceManager>();
        }
    }


    /// <summary>
    /// 查询所有分机
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public Task<List<Tel>> QueryTelsAsync(CancellationToken cancellationToken)
        => _newRockDeviceManager.QueryTelsAsync(_callcenterOptions.Value.NewRock, cancellationToken);

    /// <summary>
    /// 查询所有分机组
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public Task<List<TelGroup>> QueryTelGroupsAsync(CancellationToken cancellationToken)
        => _newRockDeviceManager.QueryTelGroupsAsync(_callcenterOptions.Value.NewRock, cancellationToken);

    /// <summary>
    /// 分机休息审批流程开始
    /// </summary>
    public async Task TelRestFlowStartAsync(FlowAssignInfo assignInfo, string? telRestId, string workflowId, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(telRestId))
            throw UserFriendlyException.SameMessage("无效分机休息编号");
        var telRest = await _telRestRepository.GetAsync(telRestId, cancellationToken);
        if (telRest == null)
            throw new UserFriendlyException($"无效分机休息编号, telRestId: {telRestId}", "无效分机休息编号");
        telRest.WorkflowId = workflowId;
        //telRest.Assign(assignInfo.FlowAssignType, assignInfo.GetHandlerIds());
        await _telRestRepository.UpdateAsync(telRest, cancellationToken);
    }

    /// <summary>
    /// 分机休息
    /// </summary>
    /// <param name="currentWork"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    //public async Task<string> RestAsync(Work currentWork, string reason, bool isApply, CancellationToken cancellationToken)
    //{
    //    var isResting = await _telRepository.IsRestingAsync(currentWork.TelNo, cancellationToken);
    //    if (!isResting)
    //    {
    //        await _newRockDeviceManager.TelRestAsync(currentWork.TelNo, cancellationToken);

    //        return await _telRestRepository.AddAsync(new TelRest(currentWork.TelId, currentWork.TelNo, currentWork.UserId, currentWork.UserName, reason, isApply),
    //            cancellationToken);
    //    }
    //    throw new UserFriendlyException("当前坐席正在休息");
    //}

    /// <summary>
    /// 分机审批通过(新)
    /// </summary>
    /// <param name="id"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task TelRestApplyPassNewAsync(string? id, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(id))
            throw UserFriendlyException.SameMessage("无效分机休息编号");

        var telRest = await _telRestRepository.GetAsync(id, cancellationToken);
        if (telRest == null)
            throw new UserFriendlyException($"无效分机休息编号, telRestId: {id}", "无效分机休息编号");

        //通知前端休息通过
        await _realtimeService.RestApplyPassAsync(telRest.UserId, cancellationToken);
    }


    /// <summary>
    /// 分机审批通过
    /// </summary>
    /// <param name="id"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task TelRestApplyPassAsync(string? id, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(id))
            throw UserFriendlyException.SameMessage("无效分机休息编号");
        var telRest = await _telRestRepository.GetAsync(id, cancellationToken);
        if (telRest == null)
            throw new UserFriendlyException($"无效分机休息编号, telRestId: {id}", "无效分机休息编号");

        //await _newRockDeviceManager.TelRestAsync(telRest.TelNo, cancellationToken);

        if (_callcenterType == AppDefaults.CallCenterType.XunShi)
        {
            telRest.StartTime = DateTime.Now;
            telRest.ApplyStatus = ETelRestApplyStatus.Resting;
            await _telRestRepository.UpdateAsync(telRest, cancellationToken);
            #region 处理设备
            var tel = _telCacheManager.GetTel(telRest.TelNo);
            foreach (var group in tel.Groups)
            {
                await _newRockDeviceManager.ModifyGroupExtAsync(_callcenterOptions.Value.NewRock, group.No, group.Distribution, group.Voice, tel.No, true, cancellationToken);
            }
            #endregion
        }

        //通知前端休息通过
        await _realtimeService.RestApplyPassAsync(telRest.UserId, cancellationToken);

    }


    /// <summary>
    /// 分机结束休息（威尔信）
    /// </summary>
    /// <param name="telNo"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<TelRest> UnRestWexAsync(string telNo, CancellationToken cancellationToken)
    {
        var restingTel = await _telRestRepository.GetAsync(d => d.TelId == telNo && !d.EndTime.HasValue, cancellationToken);
        if (restingTel is null)
            throw UserFriendlyException.SameMessage("未查询到分机休息信息");
        restingTel.EndRest();
        await _telRestRepository.UpdateAsync(restingTel, cancellationToken);
        return restingTel;
    }


    /// <summary>
    /// 分机结束休息
    /// </summary>
    /// <param name="telId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<TelRest> UnRestAsync(string telId, CancellationToken cancellationToken)
    {
        var tel = await _telRepository.GetAsync(telId, cancellationToken);
        if (tel is null)
            throw new UserFriendlyException("无效分机编号");
        //await _newRockDeviceManager.TelEndRestAsync(tel.No, cancellationToken);
        var restingTel = await _telRestRepository.GetAsync(d => d.TelId == telId && !d.EndTime.HasValue, cancellationToken);
        if (restingTel is null)
            throw new UserFriendlyException("未查询到分机休息信息");
        restingTel.EndRest();
        await _telRestRepository.UpdateAsync(restingTel, cancellationToken);
        if (_appOptions.Value.GetDefaultAppScopeConfiguration().CallCenterType == AppDefaults.CallCenterType.XunShi)
        {
            #region 处理设备
            var telCache = _telCacheManager.GetTel(tel.No);
            //更新分机组
            foreach (var group in telCache.Groups)
            {
                await _newRockDeviceManager.ModifyGroupExtAsync(_callcenterOptions.Value.NewRock, group.No, group.Distribution, group.Voice, "", true, cancellationToken);
            }

            #endregion
        }
        return restingTel;
    }

    /// <summary>
    /// 保持通话
    /// </summary>
    /// <param name="telId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task HoldAsync(string telId, string userId, string userName, string callId, CancellationToken cancellationToken)
    {
        var isHolding = await _telHoldRepository.IsHoldingAsync(telId, userId, callId, cancellationToken);
        if (!isHolding)
        {
            var tel = await _telRepository.GetAsync(telId, cancellationToken);
            if (tel is null)
                throw new UserFriendlyException("无效分机编号");
            await _newRockDeviceManager.HoldAsync(_callcenterOptions.Value.NewRock, tel.No, cancellationToken);
            await _telHoldRepository.AddAsync(new Calls.TelHold() { TelId = telId, TelNo = tel.No, UserId = userId, UserName = userName, CallId = callId }, cancellationToken);
        }
    }

    /// <summary>
    /// 恢复通话(解除hold状态)
    /// </summary>
    /// <param name="telId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task UnHoldAsync(string telId, string userId, string callId, CancellationToken cancellationToken)
    {
        var tel = await _telRepository.GetAsync(telId, cancellationToken);
        if (tel is null)
            throw new UserFriendlyException("无效分机编号");
        await _newRockDeviceManager.UnHoldAsync(_callcenterOptions.Value.NewRock, tel.No, cancellationToken);
        var holdingTel = await _telHoldRepository.GetAsync(d => d.TelId == telId && d.TelNo == tel.No && d.UserId == userId && d.CallId == callId && !d.EndTime.HasValue);
        if (holdingTel is null)
            throw new UserFriendlyException("未找到分机保持信息");
        holdingTel.EndHold();
        await _telHoldRepository.UpdateAsync(holdingTel, cancellationToken);
    }

    /// <summary>
    /// 开启静音
    /// </summary>
    /// <param name="telId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="UserFriendlyException"></exception>
    public async Task MuteAsync(string telId, CancellationToken cancellationToken)
    {
        var tel = await _telRepository.GetAsync(telId, cancellationToken);
        if (tel is null)
            throw new UserFriendlyException("无效分机编号");
        await _newRockDeviceManager.MuteAsync(_callcenterOptions.Value.NewRock, tel.No, cancellationToken);
    }

    /// <summary>
    /// 解除静音
    /// </summary>
    /// <param name="telId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task UnMuteAsync(string telId, CancellationToken cancellationToken)
    {
        var tel = await _telRepository.GetAsync(telId, cancellationToken);
        if (tel is null)
            throw new UserFriendlyException("无效分机编号");
        await _newRockDeviceManager.MuteAsync(_callcenterOptions.Value.NewRock, tel.No, cancellationToken);
    }
}