using System.Data;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using log4net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SparkClient.Model.Entity.ApiEntity;
using SparkClient.Model.Helper;
using System.Configuration;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using SparkClient.Model.Common;
using SparkClient.ViewModel.Configuration;

namespace SparkClient.Model.Services
{
    public class AlgorithmServer
    {
        private readonly AlgorithmConfigVM _algorithmConfigVM;

        public AlgorithmServer()
        {
            _algorithmConfigVM = new AlgorithmConfigVM();
        }
        private static readonly ILog Logger = LogManager.GetLogger(typeof(AlgorithmServer));
        // 导入 C++ DLL 中的 DetectDiamond 函数
        [DllImport("diamond_cut_inspector.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr DetectDiamond(string jsonData);
        // 导入 C++ DLL 中的 FreeMemory 函数
        [DllImport("diamond_cut_inspector.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        private static extern void FreeString(IntPtr ptr);
        
        // 添加公共方法
        public AlgorithmResultEntity CallParseJsonAndReturnActions(string shape, string shape_mode, string image_files)
        {
            try
            {
                //半圆
                string circleSql = $"SELECT VALUE FROM CUTTER_CONFIG WHERE KEY = 'half_circle'";
                DataTable circleTable = DataBaseHelper.ExecuteQuery(circleSql);
                object halfCircleValue = circleTable.Rows[0][0];
                bool.TryParse(halfCircleValue.ToString(), out bool boolResult);
                bool half_circle = boolResult;

                //算法配置参数,初始化算法配置数据并获取 AlgorithmConfigJson
                _algorithmConfigVM.InitAlgorithmData(null);
                string algo_config = _algorithmConfigVM.AlgorithmConfigJson;

                
                //图片根目录
                string? image_file_base_path = ConfigurationManager.AppSettings["ImageFileBasePath"];
                if (string.IsNullOrEmpty(image_file_base_path))
                {
                    throw new InvalidOperationException("ImageFileBasePath is not configured in AppSettings.");
                }

                // 获取 log4net 日志文件所在的目录
                string? log4NetLogDirectory =
                    Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                // 构建C++ DLL 日志文件路径
                string algorithm_log_path = Path.Combine(log4NetLogDirectory, "logs");

                // 将所有变量拼接成一个 JSON 对象
                JObject jsonData = new JObject(
                    new JProperty("shape", shape),
                    new JProperty("shape_mode", shape_mode),
                    new JProperty("image_file_base_path", image_file_base_path),
                    new JProperty("image_files", JToken.Parse(image_files)),
                    new JProperty("half_circle", half_circle),
                    new JProperty("algorithm_log_path", algorithm_log_path),
                    new JProperty("algo_config", JObject.Parse(algo_config))
                );

                string jsonDataString = jsonData.ToString().Replace("\"", "\\\"");
                //string jsonDataString = jsonData.ToString();
                // // 调用 C++ DLL 函数解析 JSON
                // IntPtr resultPtr = DetectDiamond(jsonDataString);
                // string resultJson = Marshal.PtrToStringAnsi(resultPtr);
                // // 释放 DLL 分配的内存
                // FreeString(resultPtr);
                // // 检查返回的 JSON 字符串是否为空或无效
                // if (string.IsNullOrEmpty(resultJson))
                // {
                //     Logger.Error("Algorithm failed or no result returned.");
                //     // 返回一个默认的 AlgorithmResultEntity 对象表示解析失败
                //     return new AlgorithmResultEntity
                //     {
                //         facets = new List<Facet>(),
                //         measurements = new Measurements()
                //     };
                // } 

                // 启动隔离的控制台应用程序
                var startInfo = new ProcessStartInfo
                {
                    FileName = "AlgorithmDllIsolationConsoleApp.exe", // 控制台应用程序路径
                    Arguments =  $"\"{jsonDataString}\"", // 将 JSON 数据作为参数传递给控制台应用程序
                    RedirectStandardOutput = true, // 获取控制台应用程序的输出
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };
                
                using (var process = Process.Start(startInfo))
                {
                    // 使用 StringBuilder 来捕获标准输出和标准错误
                    var outputBuilder = new StringBuilder();
                    var errorBuilder = new StringBuilder();
                    
                    // 订阅标准输出事件
                    process.OutputDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                        {
                            // 当 e.Data 为 null 时,表示读取完成
                            outputBuilder.AppendLine(e.Data);
                            Console.WriteLine($"Output: {e.Data}");
                            return;
                        }
                        // 将输出数据追加到 outputBuilder
                        outputBuilder.AppendLine(e.Data);
                        // 打印输出数据到控制台
                        Console.WriteLine($"Output: {e.Data}");
                    };

                    // 订阅标准错误事件
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                        {
                            // 当 e.Data 为 null 时,表示读取完成
                            errorBuilder.AppendLine(e.Data);
                            Logger.Error($"Error Output: {e.Data}");
                            return;
                        }
                        // 将错误数据追加到 errorBuilder
                        errorBuilder.AppendLine(e.Data);
                        // 记录错误数据到日志
                        Logger.Error($"Error Output: {e.Data}");
                    };

                    // 开始异步读取
                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    // 等待控制台应用程序结束
                    process.WaitForExit();

                    // 等待异步读取完成
                    //Task.WaitAll(outputTcs.Task, errorTcs.Task);
                    
                    // 获取结果
                    string resultJson = outputBuilder.ToString();
                    string errorOutput = errorBuilder.ToString();

                
                    // 如果控制台应用程序有错误输出
                    if (!string.IsNullOrEmpty(errorOutput))
                    {
                        Logger.Error($"Console App Error: {errorOutput}");
                    }
                
                    // 如果没有结果或失败
                    if (string.IsNullOrEmpty(resultJson))
                    {
                        Logger.Error("Algorithm failed or no result returned.");
                        return new AlgorithmResultEntity
                        {
                            facets = new List<Facet>(),
                            measurements = new Measurements()
                        };
                    }

                    // 反序列化 JSON 字符串为 AlgorithmResultEntity 对象
                    var result = JsonConvert.DeserializeObject<AlgorithmResultEntity>(resultJson);

                    // 检查反序列化结果是否为 null
                    if (result == null)
                    {
                        // 返回一个默认的 AlgorithmResultEntity 对象表示解析失败
                        return new AlgorithmResultEntity
                        {
                            facets = new List<Facet>(),
                            measurements = new Measurements()
                        };
                    }

                    // 记录算法失败的状态
                    Logger.Info($"Algorithm failed with status: {result.status}");
                    // 记录算法失败的错误信息
                    Logger.Info($"Algorithm failed with errorMsg: {result.error_msg}");
                    // 处理 C++ DLL 日志文件
                    //ProcessDllLog();
                    // 算法调用失败时,保存图片到历史记录文件夹
                    // if (result.status == StatusCodes.AlgorithmFailed)
                    // {
                    //     HandleAlgorithmFailure(image_files);
                    // }
                    return result;
                }
            }
            catch (Exception ex)
            {
                // 记录日志或处理异常
                Logger.Error($"Error in CallParseJsonAndReturnActions: {ex.Message}");
                Logger.Error($"Stack Trace: {ex.StackTrace}");
                // 如果有 InnerException,打印出来
                if (ex.InnerException != null)
                {
                    Logger.Error($"Inner Exception: {ex.InnerException.Message}");
                    Logger.Error($"Inner Stack Trace: {ex.InnerException.StackTrace}");
                }

                // 返回一个默认的 AlgorithmResultEntity 对象表示解析失败
                return new AlgorithmResultEntity
                {
                    facets = new List<Facet>(),
                    measurements = new Measurements()
                };
            }
        }
        
        /// <summary>
        /// 处理算法调用失败时的逻辑,包括保存图片到历史记录文件夹
        /// </summary>
        /// <param name="image_files">图片文件路径的 JSON 字符串</param>
        private void HandleAlgorithmFailure(string image_files)
        {
            
            // 从配置文件中读取 imageHistoryPath
            // 定义历史记录文件夹路径
            string? imageHistoryPath = ConfigurationManager.AppSettings["ImageHistoryPath"];
            if (string.IsNullOrEmpty(imageHistoryPath))
            {
                Logger.Error("ImageHistoryPath is not configured in AppSettings.");
                return;
            }

            // 生成时间戳,格式为 yyyyMMddHHmmss
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
            // 组合新的文件夹路径
            string newFolderPath = Path.Combine(imageHistoryPath, $"image-{timestamp}");

            // 检查 D 盘内存空间
            DriveInfo dDrive = new DriveInfo("D");
            long requiredSpace = 1000L * 1024 * 1024 * 1024; // 10GB
            if (dDrive.TotalFreeSpace < requiredSpace)
            {
                // 如果 D 盘空间不足 10GB,删除最早创建的10个文件夹
                DirectoryInfo historyDir = new DirectoryInfo(imageHistoryPath); // 获取历史记录文件夹的信息
                DirectoryInfo[] subDirs = historyDir.GetDirectories(); // 获取历史记录文件夹中的所有子文件夹
                if (subDirs.Length > 0)
                {
                    // 按创建时间排序子文件夹
                    var orderedSubDirs = subDirs.OrderBy(d => d.CreationTime).ToList();
                    int foldersToDelete = Math.Min(10, orderedSubDirs.Count);

                    // 删除最早的 10 个文件夹,如果不够 10 个则全删掉
                    for (int i = 0; i < foldersToDelete; i++)
                    {
                        orderedSubDirs[i].Delete(true);
                    }
                }
            }

            // 创建新文件夹
            Directory.CreateDirectory(newFolderPath);

            // 保存图片到新文件夹
            try
            {
                // 解析 image_files JSON 数组
                JArray imageFilesArray = JArray.Parse(image_files);
                string[] imageFiles = imageFilesArray.Select(token => token.ToString()).ToArray();

                string? imageBasePath = ConfigurationManager.AppSettings["ImageFileBasePath"]; // 图片根目录
                if (string.IsNullOrEmpty(imageBasePath))
                {
                    Logger.Error("ImageFileBasePath is not configured in AppSettings.");
                    return;
                }

                foreach (string imageFile in imageFiles)
                {
                    // 获取文件名
                    string fileName = Path.GetFileName(imageFile);
                    // 构建完整的源文件路径
                    string sourcePath = Path.Combine(imageBasePath, imageFile);
                    // 组合目标路径
                    string destinationPath = Path.Combine(newFolderPath, fileName);
                    // 复制文件到目标路径,如果目标文件已存在则覆盖
                    File.Copy(sourcePath, destinationPath, true);
                }
            }
            catch (JsonException ex)
            {
                // 记录日志或处理异常
                Logger.Error($"Error parsing image_files JSON: {ex.Message}");
                Logger.Error($"Stack Trace: {ex.StackTrace}");
            }
            catch (Exception ex)
            {
                // 记录其他异常
                Logger.Error($"Error saving images: {ex.Message}");
                Logger.Error($"Stack Trace: {ex.StackTrace}");
            }
        }
                
        /// <summary>
        /// 处理 C++ DLL 的日志文件,将其复制到 log4net 日志目录下的 logs 文件夹,并记录其内容到日志中
        /// </summary>
        private void ProcessDllLog()
        {
            try
            {
                // 获取系统临时目录路径(TMP 或 TEMP 环境变量)
                string? tempDirectory = Environment.GetEnvironmentVariable("TMP") ?? Environment.GetEnvironmentVariable("TEMP");
                if (tempDirectory != null)
                {
                    // 构建搜索模式
                    string searchPattern = "*diamond_cut_inspector*";
                    // 获取所有匹配的文件
                    string[] logFiles = Directory.GetFiles(tempDirectory, searchPattern, SearchOption.TopDirectoryOnly);
                    if (logFiles.Length > 0)
                    {
                        // 找到最新的日志文件
                        string latestLogFile = logFiles.OrderByDescending(file => new FileInfo(file).LastWriteTime).First();
                        // 获取 log4net 日志文件所在的目录
                        string log4netLogDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                        if (log4netLogDirectory != null)
                        {
                            // 构建 logs 目录路径
                            string logsDirectory = Path.Combine(log4netLogDirectory, "logs");
                            // 确保 logs 目录存在
                            Directory.CreateDirectory(logsDirectory);
                            // 构建目标文件路径
                            string targetFilePath = Path.Combine(logsDirectory, Path.GetFileName(latestLogFile));
                            // 复制最新日志文件到 logs 目录
                            File.Copy(latestLogFile, targetFilePath, true);
                            // 读取复制后的日志文件的内容
                            string dllLogContent = File.ReadAllText(targetFilePath);
                            // 记录 C++ DLL 日志文件的内容到日志中
                            Logger.Error("C++ DLL Log Content:");
                            Logger.Error(dllLogContent);
                        }
                        else
                        {
                            Logger.Error("Unable to determine the log4net log directory.");
                        }
                    }
                    else
                    {
                        // 如果没有找到匹配的日志文件,记录错误信息
                        Logger.Error("No C++ DLL log files found matching the pattern '*diamond_cut_inspector*.log'.");
                    }
                }
                else
                {
                    // 如果无法获取临时目录路径,记录错误信息
                    Logger.Error("Unable to determine the temporary directory path.");
                }
            }
            catch (Exception ex)
            {
                // 记录读取或复制日志文件时的异常
                Logger.Error($"Error processing C++ DLL log file: {ex.Message}");
                Logger.Error($"Stack Trace: {ex.StackTrace}");
            }
        }
    }

}