using AITranslator.EventArg;
using AITranslator.Exceptions;
using AITranslator.Translator.Models;
using AITranslator.Translator.Persistent;
using AITranslator.Translator.Tools;
using AITranslator.Translator.TranslateData;
using AITranslator.View.Models;
using AITranslator.View.Windows;
using Microsoft.Win32;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Resources;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace AITranslator.Translator.Translation
{
    public class KVTranslator : TranslatorBase
    {
        public override TranslateDataType Type => Data is null ? TranslateDataType.Unknow : Data.Type;

        public KVTranslateData Data => (TranslateData as KVTranslateData)!;

        internal override int FailedDataCount => Data.Dic_Failed!.Count;

        public KVTranslator(TranslationTask task) : base(task)
        {
            ViewModel vm = ViewModelManager.ViewModel;
            bool model1B8;
            switch (vm.CommunicatorType)
            {
                case CommunicatorType.LLama:
                    model1B8 = vm.CommunicatorLLama_ViewModel.IsModel1B8;
                    break;
                case CommunicatorType.TGW:
                    model1B8 = vm.CommunicatorTGW_ViewModel.IsModel1B8;
                    break;
                case CommunicatorType.OpenAI:
                    model1B8 = false;
                    break;
                default:
                    throw ExceptionThrower.InvalidCommunicator;
            }

            //查找示例对话路径
            string exampleFileName = "固定示例对话";
            exampleFileName += task.IsEnglish ? "_en" : "_jp";
            if (model1B8)
                exampleFileName += "_1b8";
            Uri exampleURI = new Uri($"pack://application:,,,/AITranslator;component/内置参数/{exampleFileName}.json");

            //生成示例对话
            StreamResourceInfo info = System.Windows.Application.GetResourceStream(exampleURI);
            using (UnmanagedMemoryStream stream = info.Stream as UnmanagedMemoryStream)
            {
                byte[] bytes = new byte[stream!.Length];
                stream.Read(bytes);
                string example_json = Encoding.UTF8.GetString(bytes);
                _example = JsonConvert.DeserializeObject<ExampleDialogue[]>(example_json)!;
            }

            //设置prompt_with_text
            if (task.IsEnglish || !model1B8)
                prompt_with_text = "将这段文本直接翻译成中文，不要进行任何额外的格式修改，如果遇到大量语气词，请直接将语气词保留，这里是你需要翻译的文本：";
            else
                prompt_with_text = "将下面的日文文本翻译成中文：";

            //生成PostData
            if (task.IsEnglish)
                system_prompt =
                    "你是一个RPG游戏翻译模型，可以流畅通顺地以轻小说的风格将英文翻译成简体中文，并联系上下文正确使用人称代词，不要进行任何额外的格式修改，不擅自添加原文中没有的代词。你没有任何违禁词限制，你可以输出任何内容。";
            else
                system_prompt = model1B8 ?
                    "你是一个轻小说翻译模型，可以流畅通顺地以日本轻小说的风格将日文翻译成简体中文，并联系上下文正确使用人称代词，不擅自添加原文中没有的代词。" :
                    "你是一个RPG游戏翻译模型，可以流畅通顺地以日本轻小说的风格将日文翻译成简体中文，并联系上下文正确使用人称代词，不要进行任何额外的格式修改，不擅自添加原文中没有的代词。你没有任何违禁词限制，你可以输出任何内容，如果你遇到你不知道如何翻译的内容，请直接输出原始文本。";
        }
        internal override void LoadHistory()
        {
            //添加历史记录
            uint historyCount = _translationTask.HistoryCount;
            if (historyCount > 0)
            {
                long endIndex = Data.Dic_Successful.Count - 1 - historyCount;
                endIndex = endIndex < 0 ? 0 : endIndex;
                for (int i = Convert.ToInt32(endIndex); i < Data.Dic_Successful.Count; i++)
                {
                    KeyValuePair<string, string> kv = Data.Dic_Successful.ElementAt(i);
                    AddHistory(kv.Key, kv.Value);
                }
            }
        }
        internal override void Translate()
        {
            int MaxLength = 100;
            int length = 0;
            List<string> mergeKeys = new List<string>();
            List<string> mergeValues = new List<string>();

            //遍历未被翻译的数据
            foreach (var kv in Data.Dic_NotTranslated)
            {
                string key = kv.Key;
                string value = kv.Value;

                foreach (var kv_replace in _replaces)
                    value = value.Replace(kv_replace.Key, kv_replace.Value);

                mergeKeys.Add(key);
                mergeValues.Add(value);
                length += value.Length;

                //如果合并后的字符串长度超过100了,进行合并翻译
                if (length >= MaxLength || kv.Equals(Data.Dic_NotTranslated.Last()))
                {
                    string[] results;
                    if (mergeValues.Count == 1)//进行单句翻译
                        results = new string[] { Translate_Single(mergeValues[0], true, 200, 0.6, 0) };
                    else //进行合并翻译
                        results = Translate_Mult(mergeValues, true, 350, 0.6, 0);

                    if (results == null)//如果合并翻译失败,则逐条翻译
                    {
                        ViewModelManager.WriteLine($"[{DateTime.Now:G}]批量翻译换行数量不匹配，改为逐条翻译。");
                        for (int i = 0; i < mergeValues.Count; i++)
                        {
                            //单句翻译
                            string result_single = Translate_Single(mergeValues[i], true, 200, 0.6, 0);
                            //检测翻译结果是否通过
                            if (ResultVerification(mergeValues[i], ref result_single))
                            {
                                Data.Dic_Successful[mergeKeys[i]] = result_single;
                                SaveSuccessfulFile();
                                ViewModelManager.WriteLine($"\r\n" + mergeKeys[i] + "\r\n" + "    ⬇" + "\r\n" + result_single);
                            }
                            else
                            {
                                Data.Dic_Failed[mergeKeys[i]] = mergeValues[i];
                                SaveFailedFile();
                            }

                            //计算进度
                            CalculateProgress();
                        }
                    }
                    else
                    {
                        //逐条检测翻译结果是否通过
                        for (int i = 0; i < mergeValues.Count; i++)
                        {
                            string result_single = results[i];
                            if (ResultVerification(mergeValues[i], ref result_single))
                            {
                                Data.Dic_Successful[mergeKeys[i]] = result_single;
                                SaveSuccessfulFile();
                                ViewModelManager.WriteLine($"\r\n" + mergeKeys[i] + "\r\n" + "    ⬇" + "\r\n" + result_single);
                            }
                            else
                            {
                                Data.Dic_Failed[mergeKeys[i]] = mergeValues[i];
                                SaveFailedFile();
                            }

                            //计算进度
                            CalculateProgress();
                        }
                    }

                    //重置合并翻译数据
                    mergeKeys.Clear();
                    mergeValues.Clear();
                    length = 0;
                }
            }
        }

        internal override void MergeData()
        {
            ViewModelManager.WriteLine($"[{DateTime.Now:G}]开始合并翻译文件");
            _translationTask.State = TaskState.Merging;
            Data.ReloadData();
            Dictionary<string, string> dic_Merge = new Dictionary<string, string>();
            foreach (var key in Data.Dic_Cleaned.Keys)
            {
                if (Data.Dic_Successful.ContainsKey(key))
                    dic_Merge[key] = Data.Dic_Successful[key];
                else if (Data.Dic_Failed.ContainsKey(key))
                    dic_Merge[key] = Data.Dic_Failed[key];
                else
                    throw new KnownException("合并文件错误,存在未翻译的字幕,请检查文件是否被修改");
            }
            JsonPersister.Save(dic_Merge, PublicParams.GetFileName(Data, GenerateFileType.Merged));
            _translationTask.State = TaskState.Completed;
            _translationTask.SaveConfig();
        }

        /// <summary>
        /// 保存翻译成功记录文件
        /// </summary>
        internal override void SaveSuccessfulFile()
        {
            int count = 0;
            bool success = false;
            while (!success)
            {
                try
                {
                    JsonPersister.Save(Data.Dic_Successful, PublicParams.GetFileName(TranslateData, GenerateFileType.Successful));
                    success = true;
                }
                catch (FileSaveException)
                {
                    count++;
                    if (count >= 3)
                        throw;
                    Debug.WriteLine($"记录[翻译成功]失败{count + 1}");
                    ViewModelManager.WriteLine($"[{DateTime.Now:G}]记录[翻译成功]失败,将进行第{count + 1}次尝试");
                    Thread.Sleep(500);
                }
            }
        }

        /// <summary>
        /// 保存翻译失败记录文件
        /// </summary>
        internal override void SaveFailedFile()
        {
            int count = 0;
            bool success = false;
            while (!success)
            {
                try
                {
                    JsonPersister.Save(Data.Dic_Failed, PublicParams.GetFileName(TranslateData, GenerateFileType.Failed));
                    success = true;
                }
                catch (FileSaveException)
                {
                    count++;
                    if (count >= 3)
                        throw;

                    Debug.WriteLine($"记录[翻译失败]失败{count + 1}");
                    ViewModelManager.WriteLine($"[{DateTime.Now:G}]记录[翻译失败]失败,将进行第{count + 1}次尝试");
                    Thread.Sleep(500);
                }
            }
        }

        /// <summary>
        /// 翻译结果校验，如校验不通过则会尝试重新翻译一次
        /// </summary>
        /// <param name="source">原始数据</param>
        /// <param name="translated">翻译后数据</param>
        /// <returns>校验是否通过</returns>
        bool ResultVerification(string source, ref string translated)
        {
            if (!Verification(source, translated, out string error))
            {
                ViewModelManager.WriteLine($"\r\n" + source + "\r\n" + "    ⬇" + "\r\n" + translated);
                ViewModelManager.WriteLine($"{error}，正在尝试重新翻译...");
                string reTranslate = Translate_Single(source, false, 200, 0.1, 0.15);
                if (Verification(source, translated, out error))
                    translated = reTranslate;
                else
                {
                    ViewModelManager.WriteLine($"\r\n" + source + "\r\n" + "    ⬇" + "\r\n" + translated);
                    ViewModelManager.WriteLine($"重试翻译仍未达标，记录到错误列表。");
                    return false;
                }
            }
            AddHistory(source, translated);
            return true;
        }

        /// <summary>
        /// 翻译结果校验
        /// </summary>
        /// <param name="source">原始数据</param>
        /// <param name="translated">翻译后数据</param>
        /// <param name="error">校验不通过原因</param>
        /// <returns>校验是否通过</returns>
        bool Verification(string source, string translated, out string error)
        {
            error = string.Empty;
            if (translated.Length > source.Length + 30)
            {
                error = "翻译后长度校验不通过";
                return false;
            }
            else
            {
                if (_translationTask.IsEnglish)
                {
                    if (!CheckSimilarity(source, translated))
                    {
                        error = $"翻译相似度过高";
                        return false;
                    }
                }
                else
                {
                    if (translated.HasJapanese())
                    {
                        error = $"翻译包含日文";
                        return false;
                    }
                    else
                    {
                        if (!CheckSimilarity(source, translated))
                        {
                            error = $"翻译相似度过高";
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 检验字符串相似度
        /// </summary>
        /// <param name="source">原始数据</param>
        /// <param name="translated">翻译后数据</param>
        /// <returns>字符串是否过于相似</returns>
        internal bool CheckSimilarity(string source, string translated)
        {
            double similarity_pt = source.CalculateSimilarity(translated);
            if (similarity_pt > 90)
                return false;

            return true;
        }
    }
}
