using DocumentFormat.OpenXml.Wordprocessing;
using Hotline.Caching.Interfaces;
using Hotline.Repository.SqlSugar.System;
using Hotline.Settings;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.Article;
using Hotline.Share.Enums.CallCenter;
using Hotline.Share.Enums.KnowledgeBase;
using Hotline.Share.Enums.Order;
using J2N.Collections.ObjectModel;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Utility.EnumExtensions;
using static Lucene.Net.Util.Fst.Util;

namespace Hotline.Application.Systems;
public class BaseDataApplication : IScopeDependency
{
    private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
    private readonly ISystemOrganizeRepository _systemOrganizeRepository;

    public BaseDataApplication(ISystemDicDataCacheManager sysDicDataCacheManager, ISystemOrganizeRepository systemOrganizeRepository)
    {
        _sysDicDataCacheManager = sysDicDataCacheManager;
        _systemOrganizeRepository = systemOrganizeRepository;
    }

    private ConcurrentDictionary<string, dynamic> _baseData = new ConcurrentDictionary<string, dynamic>();

    #region 内部方法
    private void Add(Type type)
    {
        var name = new StackTrace().GetFrame(1).GetMethod().Name;
        var method = typeof(EnumExts).GetMethod("GetDescriptions", BindingFlags.Static | BindingFlags.Public);
        var genericMethod = method.MakeGenericMethod(type);
        var result = genericMethod.Invoke(null, null);
        _baseData.TryAdd(name, result);
    }

    private void Add(string key)
    {
        var name = new StackTrace().GetFrame(1).GetMethod().Name;
        var result = _sysDicDataCacheManager
            .GetSysDicDataCache(key)
            .Where(x => x.DicDataValue != "-1")
            .Select(m => new { m.Id, m.DicDataName, m.DicDataValue })
            .ToList();
        _baseData.TryAdd(name, result);
    }
    #endregion

    public BaseDataApplication Source()
    {
        Add(typeof(ESource));
        return this;
    }

    public BaseDataApplication VisitType()
    {
        Add(typeof(EVisitType));
        return this;
    }

    public Dictionary<string, dynamic> Build()
    {
        var newDict = _baseData.ToDictionary(
            entry => char.ToLower(entry.Key[0], CultureInfo.InvariantCulture) + entry.Key.Substring(1),
            entry => entry.Value
        );

        return newDict;
    }

    public BaseDataApplication VoiceEvaluate()
    {
        Add(typeof(EVoiceEvaluate));
        return this;
    }

    public BaseDataApplication SeatEvaluate()
    {
        Add(typeof(ESeatEvaluate));
        return this;
    }

    public BaseDataApplication VisitSatisfaction()
    {
        Add(SysDicTypeConsts.VisitSatisfaction);
        return this;
    }

    public BaseDataApplication VisitManner()
    {
        Add(SysDicTypeConsts.VisitManner);
        return this;
    }

    public BaseDataApplication VisitStateQuery()
    {
        Add(typeof(EVisitStateQuery));
        return this;
    }

    public BaseDataApplication DissatisfiedReason()
    {
        Add(SysDicTypeConsts.DissatisfiedReason);
        return this;
    }

    public BaseDataApplication CallForwardingSource()
    {
        Add(SysDicTypeConsts.CallForwardingSource);
        return this;
    }

    public BaseDataApplication CallForwardingType()
    {
        Add(SysDicTypeConsts.CallForwardingType);
        return this;
    }
    public BaseDataApplication EndBy()
    {
        Add(typeof(EEndBy));
        return this;
    }

    public BaseDataApplication OrgsOptions(ISessionContext sessionContext)
    {
        IReadOnlyList<SystemOrganize> items;
        if (sessionContext.OrgIsCenter)
            items = _systemOrganizeRepository.GetOrgJson().GetAwaiter().GetResult();
        else
            items = _systemOrganizeRepository.GetOrgJsonForUser(sessionContext.RequiredOrgId).GetAwaiter().GetResult();
        _baseData.TryAdd("OrgsOptions", items);
        return this;
    }

    public BaseDataApplication AttitudeType()
    {
        Add(typeof(EAttitudeType));
        return this;
    }

    public BaseDataApplication FileType(EFileType ignoreFileType = EFileType.None)
    {
        var items = EnumExts.GetDescriptions<EFileType>();
        var filteredDictionary = items
             .Where(kvp => (ignoreFileType & (EFileType)kvp.Key) == 0)
             .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
             .ToList();
        _baseData.TryAdd("FileType", filteredDictionary);

        return this;
    }

    public BaseDataApplication Add(string name, List<KeyValuePair<int, string>> items)
    {
        _baseData.TryAdd(name, items);
        return this;
    }

    public BaseDataApplication Add(string name, List<KeyValuePair<string, string>> items)
    {
	    _baseData.TryAdd(name, items);
	    return this;
    }

	public BaseDataApplication SourceChannel()
    {
        Add(SysDicTypeConsts.SourceChannel);
        return this;
    }

    public BaseDataApplication KnowledgeRetrievalType(int[] ignoreFileType)
    {
        var items = EnumExts.GetDescriptions<EKnowledgeRetrievalType>();
        _baseData.TryAdd("KnowledgeRetrievalType", items.Where(m => !ignoreFileType.Contains(m.Key)).ToList());
        return this;
    }

    public BaseDataApplication KnowledgeHotWordType()
    {
        Add(typeof(EKnowledgeHotWordType));
        return this;
    }
}
