using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace XPrint.Image
{
    /// <summary>
    /// 使用potrace将位图转换为彩色SVG的工具类（透明背景版本）
    /// </summary>
    public class ColorPotraceConverter
    {
        #region 外部程序路径配置
        private string _pngquantPath = "pngquant";
        private string _pngnqPath = "pngnq";
        private string _convertPath = "magick convert";
        private string _identifyPath = "magick identify";
        private string _potracePath = "potrace";
        private string _potraceOptions = "";
        #endregion

        #region 配置参数
        public int MaxCommandLength { get; set; } = 1900;
        public int VerboseLevel { get; set; } = 0;
        public int Despeckle { get; set; } = 2;
        public float SmoothCorners { get; set; } = 1.0f;
        public float OptimizePaths { get; set; } = 0.2f;
        public bool Stack { get; set; } = false;
        public float Prescale { get; set; } = 1.0f;
        public bool Background { get; set; } = false; // 不再用于设置实体背景
        public string Width { get; set; } = null;
        public string Height { get; set; } = null;
        public string Dither { get; set; } = null;
        public int? Colors { get; set; } = null;
        public string RemapPalette { get; set; } = null;
        public string QuantizationAlgorithm { get; set; } = "mc";
        #endregion

        /// <summary>
        /// 初始化彩色SVG转换器
        /// </summary>
        public ColorPotraceConverter() { }

        /// <summary>
        /// 设置外部程序路径
        /// </summary>
        public void SetExternalProgramPaths(string potracePath, string convertPath = null,
                                          string identifyPath = null, string pngquantPath = null, string pngnqPath = null)
        {
            if (!string.IsNullOrEmpty(potracePath))
                _potracePath = potracePath;

            if (!string.IsNullOrEmpty(convertPath))
                _convertPath = convertPath;

            if (!string.IsNullOrEmpty(identifyPath))
                _identifyPath = identifyPath;

            if (!string.IsNullOrEmpty(pngquantPath))
                _pngquantPath = pngquantPath;

            if (!string.IsNullOrEmpty(pngnqPath))
                _pngnqPath = pngnqPath;
        }

        /// <summary>
        /// 转换多个图像文件为彩色SVG（透明背景）
        /// </summary>
        public void ConvertFiles(List<string> inputFiles, string outputPattern, int? coreCount = null)
        {
            // 解析输入输出文件对
            var filePairs = GetInputOutputPairs(inputFiles, outputPattern);
            if (!filePairs.Any())
            {
                Report("没有找到有效的输入文件");
                return;
            }

            // 确定进程数
            int processCount = coreCount ?? Environment.ProcessorCount;
            processCount = Math.Max(1, processCount);

            Report($"开始处理 {filePairs.Count} 个文件，使用 {processCount} 个进程");

            // 创建临时目录
            string tempDir = Path.Combine(Path.GetTempPath(), "ColorPotrace_" + Guid.NewGuid().ToString("N"));
            Directory.CreateDirectory(tempDir);

            try
            {
                // 并行处理文件
                Parallel.ForEach(filePairs, new ParallelOptions { MaxDegreeOfParallelism = processCount },
                    pair => ConvertSingleFile(pair.Input, pair.Output, tempDir));
            }
            finally
            {
                // 清理临时文件
                if (Directory.Exists(tempDir))
                {
                    try
                    {
                        Directory.Delete(tempDir, true);
                    }
                    catch (Exception ex)
                    {
                        Report($"清理临时文件时出错: {ex.Message}", 1);
                    }
                }
            }

            Report("所有文件处理完成");
        }

        /// <summary>
        /// 转换单个文件为彩色SVG（透明背景）
        /// </summary>
        private void ConvertSingleFile(string inputPath, string outputPath, string tempDir)
        {
            try
            {
                Report($"处理文件: {inputPath} -> {outputPath}", 1);

                // 确保输出目录存在
                string outputDir = Path.GetDirectoryName(outputPath);
                if (!Directory.Exists(outputDir))
                    Directory.CreateDirectory(outputDir);

                // 生成临时文件名
                string baseName = Path.GetFileNameWithoutExtension(inputPath);
                string scaledFile = Path.Combine(tempDir, $"{baseName}~scaled.png");
                string reducedFile = Path.Combine(tempDir, $"{baseName}~reduced.png");

                // 步骤1: 重缩放图像 - 保留透明度
                string filter = (Colors == 0) ? "point" : "lanczos";
                RescaleImageWithTransparency(inputPath, scaledFile, Prescale, filter);

                // 步骤2: 缩减颜色或重映射颜色 - 保留透明度
                if (Colors.HasValue && Colors.Value > 0)
                {
                    QuantizeImageWithTransparency(scaledFile, reducedFile, Colors.Value, QuantizationAlgorithm, Dither);
                }
                else if (!string.IsNullOrEmpty(RemapPalette))
                {
                    RemapImageColorsWithTransparency(scaledFile, reducedFile, RemapPalette, Dither);
                }
                else
                {
                    File.Copy(scaledFile, reducedFile, true);
                }

                // 步骤3: 提取颜色表（排除透明色）
                List<string> colorTable = GetColorTableExcludingTransparent(reducedFile);
                if (colorTable.Count == 0)
                {
                    Report("无法从图像中提取颜色表（可能全是透明）", 1);
                    return;
                }

                Report($"发现 {colorTable.Count} 种颜色（已排除透明色）", 1);

                // 步骤4: 为每种颜色创建孤立图层并描摹
                List<string> traceFiles = new List<string>();
                for (int i = 0; i < colorTable.Count; i++)
                {
                    string color = colorTable[i];
                    string isolatedFile = Path.Combine(tempDir, $"{baseName}~isolated_{i}.png");
                    string traceFile = Path.Combine(tempDir, $"{baseName}~trace_{i}.svg");

                    // 孤立颜色 - 保留透明区域
                    IsolateColorWithTransparency(reducedFile, isolatedFile, color, colorTable, Stack, tempDir);

                    // 描摹 - 确保透明区域不被填充
                    TraceImage(isolatedFile, traceFile, color);
                    traceFiles.Add(traceFile);
                }

                // 步骤5: 合并所有SVG图层（确保背景透明）
                MergeSvgLayersWithTransparentBackground(traceFiles, outputPath);

                // 清理临时文件
                foreach (var file in traceFiles)
                    DeleteFile(file);

                DeleteFile(scaledFile);
                DeleteFile(reducedFile);
                DeleteFile(Path.Combine(tempDir, $"{baseName}~temp.png"));
            }
            catch (Exception ex)
            {
                Report($"处理文件时出错: {ex.Message}", 1);
                throw;
            }
        }

        #region 图像处理方法（支持透明）
        /// <summary>
        /// 重缩放图像并保留透明度
        /// </summary>
        private void RescaleImageWithTransparency(string source, string destination, float scale, string filter)
        {
            if (scale == 1.0f)
            {
                // 不缩放，直接复制或转换为PNG并保留透明度
                if (Path.GetExtension(source).Equals(".png", StringComparison.OrdinalIgnoreCase))
                {
                    File.Copy(source, destination, true);
                }
                else
                {
                    string command = $"{_convertPath} \"{source}\" -background none -alpha on \"{destination}\"";
                    RunCommand(command);
                }
            }
            else
            {
                int scalePercent = (int)(scale * 100);
                string command = $"{_convertPath} \"{source}\" -filter {filter} -resize {scalePercent}% " +
                                $"-background none -alpha on \"{destination}\"";
                RunCommand(command);
            }
        }

        /// <summary>
        /// 量化缩减图像颜色并强制保留透明度
        /// </summary>
        /// <param name="source">源图像路径</param>
        /// <param name="destination">目标图像路径</param>
        /// <param name="colorCount">目标颜色数量</param>
        /// <param name="algorithm">量化算法</param>
        /// <param name="dither">拟色算法</param>
        private void QuantizeImageWithTransparency(
            string source,
            string destination,
            int colorCount,
            string algorithm,
            string dither)
        {
            // 验证源文件是否包含alpha通道
            if (!HasAlphaChannel(source))
            {
                Report($"警告: 源文件 {Path.GetFileName(source)} 不包含透明度信息", 1);
            }

            // 无需量化，直接复制文件并确保保留透明度
            if (colorCount <= 1)
            {
                PreserveTransparencyCopy(source, destination);
                return;
            }

            // 根据选择的算法执行不同的量化处理
            switch (algorithm.ToLower())
            {
                // 中切算法（增强透明度保护）
                case "mc":
                    ProcessMedianCutAlgorithm(source, destination, colorCount, dither);
                    break;

                // 自适应空间细分算法
                case "as":
                    ProcessAdaptiveSubdivisionAlgorithm(source, destination, colorCount, dither);
                    break;

                // 神经量化算法
                case "nq":
                    ProcessNeuralQuantizationAlgorithm(source, destination, colorCount, dither);
                    break;

                // 未知算法处理
                default:
                    throw new ArgumentException($"未知的量化算法: {algorithm}");
            }

            // 验证处理后的文件是否保留了透明度
            if (!HasAlphaChannel(destination))
            {
                Report($"警告: 处理后文件 {Path.GetFileName(destination)} 丢失了透明度信息", 1);
                // 尝试恢复透明度
                RestoreTransparency(source, destination);
            }
        }

        /// <summary>
        /// 检查图像是否包含alpha通道
        /// </summary>
        private bool HasAlphaChannel(string imagePath)
        {
            try
            {
                string command = $"{_identifyPath} -format \"%[channels]\" \"{imagePath}\"";
                string output = RunCommand(command, true).ToLower();
                return output.Contains("a") || output.Contains("alpha");
            }
            catch
            {
                // 命令执行失败时假设包含alpha通道
                return true;
            }
        }

        /// <summary>
        /// 复制文件并确保保留透明度
        /// </summary>
        private void PreserveTransparencyCopy(string source, string destination)
        {
            // 使用convert命令而非直接复制，确保透明度保留
            string command = $"{_convertPath} \"{source}\" " +
                           "-alpha on " +
                           "-background none " +
                           "-define png:color-type=6 " + // 明确指定带alpha通道的PNG格式
                           "\"{destination}\"";
            RunCommand(command);
        }

        /// <summary>
        /// 尝试恢复丢失的透明度
        /// </summary>
        private void RestoreTransparency(string originalImage, string processedImage)
        {
            string tempFile = Path.ChangeExtension(processedImage, ".tmp.png");

            // 使用原始图像的alpha通道修复处理后的图像
            string command = $"{_convertPath} \"{processedImage}\" " +
                           "-alpha off " +
                           "( \"{originalImage}\" -alpha extract ) " +
                           "-alpha off -compose CopyOpacity -composite " +
                           "-define png:color-type=6 " +
                           "\"{tempFile}\"";

            try
            {
                RunCommand(command);

                if (File.Exists(tempFile))
                {
                    File.Delete(processedImage);
                    File.Move(tempFile, processedImage);
                    Report("已成功恢复透明度信息", 1);
                }
            }
            catch (Exception ex)
            {
                Report($"恢复透明度失败: {ex.Message}", 1);
                if (File.Exists(tempFile))
                    File.Delete(tempFile);
            }
        }

        /// <summary>
        /// 使用中切算法处理图像量化（增强透明度保护）
        /// </summary>
        private void ProcessMedianCutAlgorithm(string source, string destination, int colorCount, string dither)
        {
            // 构建拟色选项
            string ditherOption = dither == "floydsteinberg" ? "" : "--nofs";

            // 构建pngquant命令（明确保留alpha通道）
            string command = $"{_pngquantPath} " +
                           $"--force " +
                           $"{ditherOption} " +
                           $"{colorCount} " +
                           $"--skip-if-larger " +
                           $"--ext .png " +
                           $"--quality 0-100 " +  // 确保质量设置不会影响透明度
                           $"-- " +
                           $"\"{source}\"";

            // 执行量化命令
            RunCommand(command);

            // 处理pngquant的输出文件（默认会在原文件名后添加-fs8后缀）
            string tempOutput = Path.ChangeExtension(source, $"-fs8.png");
            File.Copy(source, tempOutput);

            // 确保目标目录存在
            string destinationDir = Path.GetDirectoryName(destination);
            if (!Directory.Exists(destinationDir))
            {
                Directory.CreateDirectory(destinationDir);
            }

            // 移动处理后的文件到目标位置
            if (File.Exists(tempOutput))
            {
                // 使用convert命令转移文件以确保透明度保留
                string convertCommand = $"{_convertPath} \"{tempOutput}\" " +
                                      "-alpha on " +
                                      "-background none " +
                                      "-define png:color-type=6 " +
                                      $"\"{destination}\"";
                RunCommand(convertCommand);

                // 删除临时文件
                File.Delete(tempOutput);
            }
            else
            {
                // 量化失败时使用带透明度保护的复制
                PreserveTransparencyCopy(source, destination);
            }
        }

        /// <summary>
        /// 使用自适应空间细分算法处理图像量化（增强透明度保护）
        /// </summary>
        private void ProcessAdaptiveSubdivisionAlgorithm(string source, string destination, int colorCount, string dither)
        {
            string ditherParam = dither ?? "None";
            string command = $"{_convertPath} \"{source}\" " +
                           $"-dither {ditherParam} " +
                           $"-colors {colorCount} " +
                           $"-alpha on " +  // 明确保留alpha通道
                           $"-background none " +  // 背景设为透明
                           $"+repage " +  // 移除虚拟画布信息
                           $"-define png:color-type=6 " +  // 强制使用带alpha的PNG格式
                           $"\"{destination}\"";

            RunCommand(command);
        }

        /// <summary>
        /// 使用神经量化算法处理图像量化（增强透明度保护）
        /// </summary>
        private void ProcessNeuralQuantizationAlgorithm(string source, string destination, int colorCount, string dither)
        {
            string ditherOption = dither == "floydsteinberg" ? "-Q f " : "";
            string tempOutputNq = Path.Combine(
                Path.GetDirectoryName(source),
                $"{Path.GetFileNameWithoutExtension(source)}~quant.png"
            );

            string command = $"{_pngnqPath} " +
                           $"-f " +
                           $"{ditherOption}" +
                           $"-d \"{Path.GetDirectoryName(source)}\" " +
                           $"-n {colorCount} " +
                           $"-e ~quant.png " +
                           $"\"{source}\"";

            RunCommand(command);

            // 移动生成的文件到目标位置，使用convert确保透明度
            if (File.Exists(tempOutputNq))
            {
                string convertCommand = $"{_convertPath} \"{tempOutputNq}\" " +
                                      "-alpha on " +
                                      "-background none " +
                                      "-define png:color-type=6 " +
                                      "\"{destination}\"";
                RunCommand(convertCommand);
                File.Delete(tempOutputNq);
            }
            else
            {
                // 量化失败时使用带透明度保护的复制
                PreserveTransparencyCopy(source, destination);
                throw new Exception("pngnq 未能生成输出文件");
            }
        }

        /// <summary>
        /// 使用调色板重映射图像颜色并保留透明度
        /// </summary>
        private void RemapImageColorsWithTransparency(string source, string destination, string paletteImage, string dither)
        {
            if (!File.Exists(paletteImage))
                throw new FileNotFoundException("未找到调色板图像", paletteImage);

            string ditherParam = dither ?? "None";
            string command = $"{_convertPath} \"{source}\" -dither {ditherParam} -remap \"{paletteImage}\" " +
                             $"-background none -alpha on \"{destination}\"";
            RunCommand(command);
        }

        /// <summary>
        /// 从图像中提取颜色表（排除透明色）
        /// </summary>
        private List<string> GetColorTableExcludingTransparent(string imagePath)
        {
            string command = $"{_convertPath} \"{imagePath}\" -unique-colors txt:-";
            string output = RunCommand(command, true, false);

            // 提取十六进制颜色并排除透明色
            MatchCollection matches = Regex.Matches(output, "#[0-9A-Fa-f]{6}");
            var colors = matches.Cast<Match>()
                                .Select(m => m.Value.ToUpper())
                                .Distinct()
                                .ToList();

            // 排除可能的透明色表示（白色在某些情况下可能代表透明）
            // 更精确的做法是检查alpha通道，但这里简化处理
            colors.Remove("#FFFFFF"); // 移除白色（如果它代表透明背景）

            return colors;
        }

        /// <summary>
        /// 孤立指定颜色并保留透明区域
        /// </summary>
        private void IsolateColorWithTransparency(string source, string destination, string targetColor,
                                                List<string> palette, bool stack, string tempDir)
        {
            int colorIndex = palette.IndexOf(targetColor);
            if (colorIndex == -1)
                throw new ArgumentException("目标颜色不在调色板中");

            // 获取不在调色板中的颜色作为临时背景和前景
            string bgTransparent = "#00000000"; // 透明色
            string fgBlack = "#000000";
            string bgAlmostWhite = GetNonPaletteColor(palette, false, new[] { bgTransparent, fgBlack });
            string fgAlmostBlack = GetNonPaletteColor(palette, true, new[] { bgAlmostWhite, bgTransparent, fgBlack });

            // 创建临时文件
            string tempFile = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(source) + "~temp.png");

            // 构建颜色替换命令 - 保留透明区域
            string commandPrefix = $"{_convertPath} \"{source}\" -alpha on";
            string commandSuffix = $" -alpha on \"{tempFile}\"";
            string commandMiddle = "";

            for (int i = 0; i < palette.Count; i++)
            {
                string fillColor = (i == colorIndex || (i > colorIndex && stack)) ? fgAlmostBlack : bgAlmostWhite;
                commandMiddle += $" -fill \"{fillColor}\" -opaque \"{palette[i]}\"";

                // 如果命令太长，执行并重置
                if (commandMiddle.Length >= MaxCommandLength || i == palette.Count - 1)
                {
                    string fullCommand = commandPrefix + commandMiddle + commandSuffix;
                    RunCommand(fullCommand);
                    commandMiddle = "";
                }
            }

            // 转换为黑白并保留透明
            string finalCommand = $"{_convertPath} \"{tempFile}\" -fill white -opaque \"{bgAlmostWhite}\" " +
                                 $"-fill black -opaque \"{fgAlmostBlack}\" -alpha on \"{destination}\"";
            RunCommand(finalCommand);
        }

        /// <summary>
        /// 描摹图像为SVG（确保透明区域不填充）
        /// </summary>
        private void TraceImage(string source, string destination, string color)
        {
            //if (!string.IsNullOrEmpty(source) && File.Exists(source))
            //{
            //    if (!source.EndsWith(".bmp") && !source.EndsWith(".BMP"))
            //    {
            //        string oldSource = source;
            //        using (var bmp = Bitmap.FromFile(source))
            //        {
            //            source = Path.Combine(Path.GetDirectoryName(source), Guid.NewGuid().ToString("N") + ".bmp");
            //            bmp.Save(source, ImageFormat.Bmp);
            //        }
            //        File.Delete(oldSource);
            //    }
            //}
            string widthParam = !string.IsNullOrEmpty(Width) ? $"--width {Width}" : "";
            string heightParam = !string.IsNullOrEmpty(Height) ? $"--height {Height}" : "";

            // 添加参数确保只填充前景，背景保持透明
            string command = $"{_potracePath} \"{source}\" {_potraceOptions} --svg -o \"{destination}\" " +
                           $"-C \"{color}\" -t {Despeckle} -a {SmoothCorners} -O {OptimizePaths} " +
                           $"{widthParam} {heightParam} --fillcolor \"{color}\"";
            RunCommand(command);
        }

        /// <summary>
        /// 合并多个SVG图层并确保背景透明
        /// </summary>
        private void MergeSvgLayersWithTransparentBackground(List<string> svgFiles, string outputPath)
        {
            // 创建一个新的SVG文档，只声明一次默认命名空间
            XNamespace svgNs = "http://www.w3.org/2000/svg";
            XDocument mergedDoc = new XDocument(
                new XElement(svgNs + "svg",
                    new XAttribute(XNamespace.Xmlns + "svg", svgNs),  // 正确声明命名空间
                    new XAttribute("version", "1.1"),
                    // 不设置背景色，保持透明
                    new XAttribute("style", "background: transparent;")
                )
            );

            XElement root = mergedDoc.Root;
            if (root == null)
                throw new InvalidOperationException("无法创建SVG根元素");

            // 记录是否已经设置了尺寸属性
            bool hasSizeAttributes = false;

            // 合并所有SVG内容
            foreach (string file in svgFiles)
            {
                XDocument doc = XDocument.Load(file);
                XElement docRoot = doc.Root;
                if (docRoot == null)
                    continue;

                // 处理第一个SVG文件的尺寸属性（只设置一次）
                if (!hasSizeAttributes)
                {
                    // 复制宽度、高度和视图框属性（排除命名空间属性）
                    foreach (XAttribute attr in docRoot.Attributes())
                    {
                        if (attr.Name.LocalName == "width" ||
                            attr.Name.LocalName == "height" ||
                            attr.Name.LocalName == "viewBox")
                        {
                            root.SetAttributeValue(attr.Name, attr.Value);
                        }
                    }
                    hasSizeAttributes = true;
                }

                // 复制所有子元素，并确保它们使用正确的命名空间
                foreach (XElement child in docRoot.Elements())
                {
                    // 移除子元素可能携带的命名空间声明，避免冲突
                    var cleanedChild = CleanElementNamespace(child, svgNs);

                    // 确保没有设置全局背景
                    if (cleanedChild.Name.LocalName == "rect" &&
                        cleanedChild.Attribute("width") != null &&
                        cleanedChild.Attribute("height") != null &&
                        cleanedChild.Attribute("fill") != null)
                    {
                        // 过滤掉可能的背景矩形
                        continue;
                    }

                    root.Add(cleanedChild);
                }
            }

            mergedDoc.Save(outputPath);
        }
        #endregion

        #region 辅助方法
        /// <summary>
        /// 获取输入输出文件对
        /// </summary>
        private List<(string Input, string Output)> GetInputOutputPairs(List<string> inputPatterns, string outputPattern)
        {
            List<(string, string)> result = new List<(string, string)>();
            HashSet<string> processedInputs = new HashSet<string>();

            foreach (string pattern in inputPatterns)
            {
                // 处理通配符
                string directory = Path.GetDirectoryName(pattern);
                string fileName = Path.GetFileName(pattern);

                if (string.IsNullOrEmpty(directory))
                    directory = Environment.CurrentDirectory;

                if (!Directory.Exists(directory))
                    continue;

                // 获取匹配的文件
                foreach (string file in Directory.EnumerateFiles(directory, fileName))
                {
                    if (processedInputs.Contains(file))
                        continue;

                    processedInputs.Add(file);

                    // 生成输出文件名
                    string baseName = Path.GetFileNameWithoutExtension(file);
                    string outputFile = outputPattern.Replace("{0}", baseName);

                    result.Add((file, outputFile));
                }
            }

            return result;
        }

        /// <summary>
        /// 运行外部命令
        /// </summary>
        private string RunCommand(string command, bool captureOutput = false, bool captureError = true)
        {
            Report($"执行命令: {command}", 2);

            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = $"/c {command}",
                UseShellExecute = false,
                RedirectStandardOutput = captureOutput,
                RedirectStandardError = captureError,
                CreateNoWindow = true
            };

            using (Process process = Process.Start(startInfo))
            {
                if (process == null)
                    throw new InvalidOperationException("无法启动进程");

                string output = captureOutput ? process.StandardOutput.ReadToEnd() : null;
                string error = captureError ? process.StandardError.ReadToEnd() : null;

                process.WaitForExit();

                if (process.ExitCode != 0)
                    throw new Exception($"命令执行失败 (代码 {process.ExitCode}): {error}");

                return output;
            }
        }

        /// <summary>
        /// 获取不在调色板中的颜色
        /// </summary>
        private string GetNonPaletteColor(List<string> palette, bool startFromBlack, IEnumerable<string> avoidColors = null)
        {
            HashSet<string> allAvoid = new HashSet<string>(palette.Select(c => c.ToUpper()));
            if (avoidColors != null)
                foreach (string color in avoidColors)
                    allAvoid.Add(color.ToUpper());

            if (startFromBlack)
            {
                // 从黑色开始查找
                for (int i = 0; i <= 0xFFFFFF; i++)
                {
                    string color = $"#{i:X6}";
                    if (!allAvoid.Contains(color))
                        return color;
                }
            }
            else
            {
                // 从白色开始查找
                for (int i = 0xFFFFFF; i >= 0; i--)
                {
                    string color = $"#{i:X6}";
                    if (!allAvoid.Contains(color))
                        return color;
                }
            }

            throw new Exception("无法找到不在调色板中的颜色");
        }

        /// <summary>
        /// 清理元素的命名空间声明，确保使用指定的命名空间
        /// </summary>
        private XElement CleanElementNamespace(XElement element, XNamespace targetNs)
        {
            // 创建一个使用目标命名空间的新元素
            XElement cleaned = new XElement(targetNs + element.Name.LocalName);

            // 复制属性，但排除命名空间声明
            foreach (XAttribute attr in element.Attributes())
            {
                if (!attr.IsNamespaceDeclaration)
                {
                    cleaned.Add(new XAttribute(attr.Name, attr.Value));
                }
            }

            // 递归清理子元素
            foreach (XElement child in element.Elements())
            {
                cleaned.Add(CleanElementNamespace(child, targetNs));
            }

            // 复制文本内容
            if (!string.IsNullOrEmpty(element.Value))
            {
                cleaned.Value = element.Value;
            }

            return cleaned;
        }

        /// <summary>
        /// 删除文件（如果存在）
        /// </summary>
        private void DeleteFile(string path)
        {
            if (File.Exists(path))
            {
                try
                {
                    File.Delete(path);
                }
                catch (Exception ex)
                {
                    Report($"无法删除临时文件 {path}: {ex.Message}", 1);
                }
            }
        }

        /// <summary>
        /// 报告信息
        /// </summary>
        private void Report(string message, int level = 1)
        {
            if (VerboseLevel >= level)
                Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {message}");
        }

        /// <summary>
        /// 获取图像宽度
        /// </summary>
        private int GetImageWidth(string imagePath)
        {
            string command = $"{_identifyPath} -ping -format \"%w\" \"{imagePath}\"";
            string output = RunCommand(command, true);

            if (int.TryParse(output, out int width))
                return width;

            throw new Exception("无法获取图像宽度");
        }
        #endregion
    }
}
