using DotNetCore.CAP;
using Hotline.Caching.Interfaces;
using Hotline.CallCenter.Calls;
using Hotline.Configurations;
using Hotline.EventBus;
using Hotline.Settings;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Dtos.Push;
using Hotline.Share.Enums.Order;
using Hotline.Share.Tools;
using Mapster;
using MediatR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text.RegularExpressions;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.Orders;
public class OrderVisitDomainService : IOrderVisitDomainService, IScopeDependency
{
    private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
    private readonly ILogger<OrderVisitDomainService> _logger;
    private readonly IRepository<Order> _orderRepository;
    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
    private readonly IOrderVisitRepository _orderVisitRepository;
    private readonly ICapPublisher _capPublisher;
    private readonly Publisher _publisher;
    private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
    private readonly ISettingOrderVisitSmsReplyRuleRepository _settingOrderVisitSmsReplyRuleRepository;
    private readonly ISystemLogRepository _logRepository;
    private readonly IRepository<OrderVisitRecord> _orderVisitRecordRepository;
    private readonly ISystemSettingCacheManager _systemSettingCacheManager;
    private readonly IMediator _mediator;

    public OrderVisitDomainService(IRepository<OrderVisitDetail> orderVisitDetailRepository,
        ILogger<OrderVisitDomainService> logger,
        IRepository<Order> orderRepository,
        ISystemDicDataCacheManager systemDicDataCacheManager,
        IOrderVisitRepository orderVisitRepository,
        ICapPublisher capPublisher, Publisher publisher,
        IOptionsSnapshot<AppConfiguration> appOptions,
        ISettingOrderVisitSmsReplyRuleRepository settingOrderVisitSmsReplyRuleRepository,
        ISystemLogRepository logRepository,
        IRepository<OrderVisitRecord> orderVisitRecordRepository,
        ISystemSettingCacheManager systemSettingCacheManager,
        IMediator mediator)
    {
        _orderVisitDetailRepository = orderVisitDetailRepository;
        _logger = logger;
        _orderRepository = orderRepository;
        _systemDicDataCacheManager = systemDicDataCacheManager;
        _orderVisitRepository = orderVisitRepository;
        _capPublisher = capPublisher;
        _publisher = publisher;
        _appOptions = appOptions;
        _settingOrderVisitSmsReplyRuleRepository = settingOrderVisitSmsReplyRuleRepository;
        _logRepository = logRepository;
        _orderVisitRecordRepository = orderVisitRecordRepository;
        _systemSettingCacheManager = systemSettingCacheManager;
        _mediator = mediator;
    }

    /// <summary>
    /// 语音回访处理
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    public async Task UpdateVoiceReplyAsync(VoiceEvaluationButton dto)
    {
        var data = await _orderVisitRepository.GetAsync(p => p.Id == dto.CustomerId);
        if (data != null)
        {
            var replyTxt = "智能电话回访不作评价";
            if (dto.Content == "1")
                replyTxt = "智能电话回访满意";
            else if (dto.Content == "2")
                replyTxt = "智能电话回访不满意";

            await UpdateSmsReplyAsync(data, replyTxt);
        }
        else
        {
            _logRepository.Add("语音回访-不处理", dto, "未查询到回访数据", "UpdateVoiceReplyAsync", 0);
        }
    }

    /// <summary>
    /// 用户回访短信回复更新回访状态
    /// </summary>
    /// <param name="dto"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task UpdateSmsReplyAsync(MessageDto data)
    {
        if (data.IsSmsReply == false || data.SmsReplyContent.IsNullOrEmpty())
        {
            _logRepository.Add("短信回访-不处理", data, "用户回复的内容为空", "UpdateSmsReplyAsync", 0);
            return;
        }

        var query = _orderVisitRepository.Queryable()
        .Includes(m => m.Order)
        .Where(m => m.Order.Contact == data.TelNumber)
        .Where(m => m.VisitState == EVisitState.SMSVisiting)
        .OrderBy(m => m.CreationTime);

#if DEBUG
        var sql = query.ToSqlString();
#endif
        var orderVisit = await query.FirstAsync();
        if (orderVisit == null)
        {
            _logRepository.Add("短信回访-不处理", query.ToSqlString(), $"根据电话号码{data.TelNumber} 和回访状态 EVisitState.SMSVisiting, 无法查询出回访信息", "UpdateSmsReplyAsync", 0);
            return;
        }

        await UpdateSmsReplyAsync(orderVisit, data.SmsReplyContent!.Trim());

    }

    /// <summary>
    /// 根据用户短信或电话回复的内容转换成系统中对应的评价
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="replyTxt"></param>
    /// <returns></returns>
    /// <exception cref="UserFriendlyException"></exception>
    public SettingOrderVisitSmsReplyRule GetVisitEvaluateByReplyTxt(string replyTxt)
    {
        var replyToEnumMap = _settingOrderVisitSmsReplyRuleRepository.GetByAppScope(_appOptions.Value.AppScope);
        if (replyToEnumMap.IsNullOrEmpty()) throw new UserFriendlyException("系统未配置短信回访规则");
        replyTxt = replyTxt.Trim();
        return replyToEnumMap.FirstOrDefault(m => new Regex(m.ReplyRegular).IsMatch(replyTxt))
            ?? throw new UserFriendlyException($"用户回复内容异常; replyTxt: {replyTxt}");
    }

    /// <summary>
    /// 超过48小时未回复短信,修改短信回访记录为默认满意
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    public async Task UpdateSmsReplyDefaultAsync(MessageDto dto)
    {
        await _orderVisitRepository.Queryable()
            .Includes(m => m.Order)
            .Where(m => m.Id == dto.ExternalId)
            .Where(m => m.VisitState == EVisitState.SMSVisiting)
            .FirstAsync()
            .Then(async orderVisit =>
            {
                // 默认满意
                await UpdateSmsReplyAsync(orderVisit, "默认满意");
            });
    }

    /// <summary>
    /// 超过48小时未回复短信,修改短信回访记录为默认满意
    /// 用户回访短信回复更新回访状态
    /// </summary>
    /// <param name="orderVisit"></param>
    /// <param name="replyTxt"></param>
    /// <returns></returns>
    private async Task UpdateSmsReplyAsync(OrderVisit orderVisit, string replyTxt)
    {
        orderVisit.Order ??= await _orderRepository.GetAsync(orderVisit.OrderId);
        //orderVisit.VisitType = EVisitType.SmsVisit;
        //if (new string[] { "4", "5", "不满意", "非常不满意" }.Contains(replyTxt))
        //{
        //    // “短信不满意待回访”状态下，由其他方式再次进行回访，回访方式需更新为最新的回访方式
        //    // 故在此置为空
        //    orderVisit.VisitType = null;
        //}
        var smsReplyRule = GetVisitEvaluateByReplyTxt(replyTxt);
        _logRepository.Add("短信回访-回复内容匹配结果", smsReplyRule, orderVisit.No, orderVisit.OrderId, 1, orderVisit.Id, replyTxt);
        var visitSatisfactionKv = smsReplyRule.GetOrgProcessingResults(_systemDicDataCacheManager.VisitSatisfaction);
        if (smsReplyRule.VisitType != null)
            orderVisit.VisitType = smsReplyRule.VisitType.Value;
        if (smsReplyRule.OrgProcessingResults != null)
            orderVisit.NowEvaluate = visitSatisfactionKv;

        orderVisit.VisitTime = DateTime.Now;
        if (smsReplyRule.VisitState != null)
            orderVisit.VisitState = smsReplyRule.VisitState.Value;
        await _orderVisitRepository.UpdateAsync(orderVisit, ignoreNullColumns: false);

        if (orderVisit.VisitState == EVisitState.Visited)
        {
            await _orderRepository.GetAsync(orderVisit.OrderId)
                .Then(async order =>
                {
                    order!.Visited(visitSatisfactionKv.Key, visitSatisfactionKv.Value);
                    await _orderRepository.UpdateAsync(order);
                });

        }
        var detailOrg = await _orderVisitDetailRepository.Queryable()
            .Where(m => m.VisitId == orderVisit.Id && m.VisitTarget == EVisitTarget.Org)
            .ToListAsync();
        foreach (var item in detailOrg)
        {
            if (smsReplyRule.OrgProcessingResults != null)
            {
                var processingResults = smsReplyRule.GetOrgProcessingResults(_systemDicDataCacheManager.VisitSatisfaction);
                item.OrgProcessingResults = processingResults;
                item.VisitContent = processingResults?.Value;
            }
            if (smsReplyRule.VisitContent != null)
                item.VisitContent = smsReplyRule.VisitContent;
            if (smsReplyRule.OrgHandledAttitude != null)
                item.OrgHandledAttitude = smsReplyRule.GetOrgHandledAttitude(_systemDicDataCacheManager.VisitSatisfaction);
            if (smsReplyRule.IsReplyToOrgVisitContent != null && smsReplyRule.IsReplyToOrgVisitContent == true)
                item.VisitContent = replyTxt;
        }
        await _orderVisitDetailRepository.UpdateRangeAsync(detailOrg);

        await _orderVisitDetailRepository.Queryable()
            .Where(m => m.VisitId == orderVisit.Id && m.VisitTarget == EVisitTarget.Seat)
            .FirstAsync()
            .Then(async detailSeat =>
            {
                if (smsReplyRule.SeatEvaluate != null || smsReplyRule.SmSVoiceEvaluate != null)
                {
                    if (smsReplyRule.SeatEvaluate != null)
                        detailSeat.SeatEvaluate ??= smsReplyRule.SeatEvaluate;
                    if (smsReplyRule.SmSVoiceEvaluate != null)
                        detailSeat.VoiceEvaluate ??= smsReplyRule.SmSVoiceEvaluate;
                    await _orderVisitDetailRepository.UpdateAsync(detailSeat);
                }
            });


        if (orderVisit.VisitState != EVisitState.Visited) return;

        orderVisit.Order.Visited(visitSatisfactionKv.Key, visitSatisfactionKv.Value);
        await _orderRepository.UpdateAsync(orderVisit.Order);
        var orderDto = orderVisit.Order.Adapt<OrderDto>();
        var first = detailOrg.First();
        if (visitSatisfactionKv.Key != null && visitSatisfactionKv.Value != null)
        {
            //推省上
            await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderVisited,
                new PublishVisitDto()
                {
                    Order = orderDto,
                    No = orderVisit.No,
                    VisitType = orderVisit.VisitType,
                    VisitName = orderVisit.CreatorName,
                    VisitTime = orderVisit.VisitTime,
                    VisitRemark = string.IsNullOrEmpty(first.VisitContent) ? first.OrgProcessingResults?.Value : first.VisitContent,
                    AreaCode = orderVisit.Order.AreaCode!,
                    SubjectResultSatifyCode = first.OrgProcessingResults.Key,
                    FirstSatisfactionCode = orderVisit.Order.FirstVisitResultCode!,
                    ClientGuid = ""
                }, cancellationToken: CancellationToken.None);

            if (_appOptions.Value.IsZiGong == true)
            {
                //回访成功后，写入回访记录信息
                await _orderVisitRecordRepository.AddAsync(new()
                {
                    No = orderVisit.No,
                    OrderId = orderVisit.OrderId,
                    VisitType = orderVisit.VisitType,
                    EmployeeId = orderVisit.EmployeeId,
                    VisitTime = orderVisit.VisitTime
                });
            }
        }
    }
}
