using Hotline.Caching.Interfaces;
using Hotline.Push.FWMessage;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Push;
using Hotline.Share.Enums.Order;
using Hotline.Share.Tools;
using Mapster;
using Mapster.Utils;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;
using static System.Runtime.InteropServices.JavaScript.JSType;

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;


    public OrderVisitDomainService(IRepository<OrderVisitDetail> orderVisitDetailRepository, ILogger<OrderVisitDomainService> logger, IRepository<Order> orderRepository, ISystemDicDataCacheManager systemDicDataCacheManager, IOrderVisitRepository orderVisitRepository)
    {
        _orderVisitDetailRepository = orderVisitDetailRepository;
        _logger = logger;
        _orderRepository = orderRepository;
        _systemDicDataCacheManager = systemDicDataCacheManager;
        _orderVisitRepository = orderVisitRepository;
    }

    /// <summary>
    /// 用户回访短信回复更新回访状态
    /// </summary>
    /// <param name="dto"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    public async Task UpdateSmsReplyAsync(MessageDto data)
    {
        _logger.LogInformation($"UpdateSmsReplyAsync 收到通知: {data.ToJson()}");
        if (data.IsSmsReply == false || data.SmsReplyContent.IsNullOrEmpty()) return;

        var orderVisits = await _orderVisitRepository.Queryable()
            .Includes(m => m.Order)
            .Where(m => m.Order.Contact == data.TelNumber)
            .Where(m => m.VisitState == EVisitState.SMSVisiting)
            .ToListAsync();

        foreach (var orderVisit in orderVisits)
        {
            await UpdateSmsReplyAsync(orderVisit, data.SmsReplyContent!.Trim());
        }
    }

    /// <summary>
    /// 根据用户短信或电话回复的内容转换成系统中对应的评价
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="replyTxt"></param>
    /// <returns></returns>
    /// <exception cref="UserFriendlyException"></exception>
    public T GetVisitEvaluateByReplyTxt<T>(string replyTxt)
    {
        Dictionary<string, string> ReplyToEnumMap = new()
        {
            { "1", $"非常满意|{EVisitState.Visited}|{ESeatEvaluate.VerySatisfied}|{EVoiceEvaluate.VerySatisfied}|5" },
            { "2", $"满意|{EVisitState.Visited}|{ESeatEvaluate.Satisfied}|{EVoiceEvaluate.Satisfied}|4"},
            { "3", $"一般|{EVisitState.Visited}|{ESeatEvaluate.Normal}|{EVoiceEvaluate.Normal}|4"},
            { "4", $"不满意|{EVisitState.SMSUnsatisfied}|{ESeatEvaluate.NoSatisfied}|{EVoiceEvaluate.NoSatisfied}|2"},
            { "5", $"非常不满意|{EVisitState.SMSUnsatisfied}|{ESeatEvaluate.NoSatisfied}|{EVoiceEvaluate.VeryNoSatisfied}|2"},
            { "默认满意", $"默认满意|{EVisitState.Visited}|{ESeatEvaluate.DefaultSatisfied}|{EVoiceEvaluate.DefaultSatisfied}|4"},
        };
        replyTxt = replyTxt.Trim();
        if (ReplyToEnumMap.TryGetValue(replyTxt, out var result) == false)
        {
            var m = ReplyToEnumMap.FirstOrDefault(item => item.Value.StartsWith(replyTxt));
            replyTxt = m.Key;
            result = m.Value;
        }

        if (result.IsNullOrEmpty()) throw new UserFriendlyException($"用户回复内容异常; replyTxt: {replyTxt}");
        var replySplit = result.Split("|");

        if (typeof(T) == typeof(string))
            return (T)(replySplit[0] as object);

        if (typeof(T) == typeof(EVisitState))
            return (T)Enum.Parse(typeof(T), replySplit[1]);

        if (typeof(T) == typeof(ESeatEvaluate))
            return (T)Enum.Parse(typeof(T), replySplit[2]);

        if (typeof(T) == typeof(EVoiceEvaluate))
            return (T)Enum.Parse(typeof(T), replySplit[3]);

        if (typeof(T) == typeof(Kv))
            return _systemDicDataCacheManager.GetVisitSatisfaction()
           .First(m => m.DicDataValue == replySplit[4]).Adapt<T>();

        return default;
    }

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

    private async Task UpdateSmsReplyAsync(OrderVisit orderVisit, string replyTxt)
    {
        if (new string[] { "4", "5" }.Contains(replyTxt))
        {
            // “短信不满意待回访”状态下，由其他方式再次进行回访，回访方式需更新为最新的回访方式
            // 故在此置为空
            orderVisit.VisitType = null;
        }
        var visitSatisfactionKv = GetVisitEvaluateByReplyTxt<Kv>(replyTxt);
        orderVisit.NowEvaluate = visitSatisfactionKv;

        orderVisit.VisitTime = DateTime.Now;
        orderVisit.VisitState = GetVisitEvaluateByReplyTxt<EVisitState>(replyTxt);
        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)
        {
            item.ReplyBackfill(visitSatisfactionKv);
        }
        await _orderVisitDetailRepository.UpdateRangeAsync(detailOrg);

        await _orderVisitDetailRepository.Queryable()
            .Where(m => m.VisitId == orderVisit.Id && m.VisitTarget == EVisitTarget.Seat)
            .FirstAsync()
            .Then(async detailSeat =>
            {
                detailSeat.ReplyBackfill(
                    GetVisitEvaluateByReplyTxt<ESeatEvaluate>(replyTxt),
                    GetVisitEvaluateByReplyTxt<EVoiceEvaluate>(replyTxt)
                    );
                await _orderVisitDetailRepository.UpdateAsync(detailSeat);
            });
    }
}
