using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using BLL.Interfaces;
using DAL.Interfaces;
using MDL.Models;
using Microsoft.Extensions.Logging;
using PdfSharp.Pdf.IO;
using ZXing;
using ZXing.Common;
using Ghostscript.NET;
using Ghostscript.NET.Rasterizer;

namespace BLL.Services
{
    /// <summary>
    /// 面单PDF缓存服务实现类
    /// </summary>
    public class LabelPdfCacheService : ILabelPdfCacheService
    {
        private readonly ILabelPdfCacheRepository _cacheRepository;
        private readonly ILabelReplaceRepository _labelReplaceRepository;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ILogger<LabelPdfCacheService> _logger;
        private const int MaxRetryCount = 3;
        private const int PdfDownloadTimeoutSeconds = 30;
        private const int MaxFileSizeBytes = 1500000;

        /// <summary>
        /// 构造函数
        /// </summary>
        public LabelPdfCacheService(
            ILabelPdfCacheRepository cacheRepository,
            ILabelReplaceRepository labelReplaceRepository,
            IHttpClientFactory httpClientFactory,
            ILogger<LabelPdfCacheService> logger)
        {
            _cacheRepository = cacheRepository;
            _labelReplaceRepository = labelReplaceRepository;
            _httpClientFactory = httpClientFactory;
            _logger = logger;
        }

        /// <summary>
        /// 获取有效的缓存记录（状态为处理成功且 pdf_bytes 不为空）。
        /// 采用两阶段查询：先查元数据做有效性校验，通过后再单独加载 pdf_bytes，
        /// 避免对无效缓存执行无谓的 BLOB 传输。
        /// </summary>
        /// <param name="waybillNumber">中性面单单号</param>
        /// <returns>含 PdfBytes 的缓存记录，缓存不存在或无效时返回 null</returns>
        public async Task<LabelPdfCache?> GetValidCacheAsync(string waybillNumber)
        {
            try
            {
                var meta = await _cacheRepository.GetMetaByWaybillNumberAsync(waybillNumber);
                if (meta == null || meta.Status != 1)
                {
                    return null;
                }

                var order = await _labelReplaceRepository.GetByWaybillNumberAsync(waybillNumber);
                if (order != null && meta.UpdatedTime < order.LabelRetrievedAt)
                {
                    _logger.LogInformation("Cache is outdated for waybill: {number}, invalidating cache", waybillNumber);
                    await InvalidateCacheAsync(waybillNumber);
                    return null;
                }

                var pdfBytes = await _cacheRepository.GetPdfBytesAsync(waybillNumber);
                if (pdfBytes == null)
                {
                    return null;
                }

                meta.PdfBytes = pdfBytes;
                return meta;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting valid cache for waybill: {number}", waybillNumber);
                return null;
            }
        }

        /// <summary>
        /// 获取有效的缓存记录，传入已查询好的订单对象可跳过内部重复查库。
        /// 采用两阶段查询：先查元数据做有效性校验，通过后再单独加载 pdf_bytes，
        /// 避免对无效缓存执行无谓的 BLOB 传输。
        /// </summary>
        /// <param name="waybillNumber">中性面单单号</param>
        /// <param name="order">已有的订单对象，传 null 时内部自行查库</param>
        /// <returns>含 PdfBytes 的缓存记录，缓存不存在或无效时返回 null</returns>
        public async Task<LabelPdfCache?> GetValidCacheAsync(string waybillNumber, LabelReplaceEntity? order)
        {
            try
            {
                var meta = await _cacheRepository.GetMetaByWaybillNumberAsync(waybillNumber);
                if (meta == null || meta.Status != 1)
                {
                    return null;
                }

                var resolvedOrder = order ?? await _labelReplaceRepository.GetByWaybillNumberAsync(waybillNumber);
                if (resolvedOrder != null && meta.UpdatedTime < resolvedOrder.LabelRetrievedAt)
                {
                    _logger.LogInformation("Cache is outdated for waybill: {number}, invalidating cache", waybillNumber);
                    await InvalidateCacheAsync(waybillNumber);
                    return null;
                }

                var pdfBytes = await _cacheRepository.GetPdfBytesAsync(waybillNumber);
                if (pdfBytes == null)
                {
                    return null;
                }

                meta.PdfBytes = pdfBytes;
                return meta;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting valid cache for waybill: {number}", waybillNumber);
                return null;
            }
        }

        /// <summary>
        /// 保存PDF缓存
        /// </summary>
        /// <param name="waybillNumber">中性面单单号</param>
        /// <param name="pdfBytes">PDF字节流</param>
        /// <param name="pageCount">PDF页数</param>
        /// <param name="fileSize">文件大小</param>
        /// <param name="originalUrl">原始标签URL</param>
        /// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
        /// <param name="customerId">客户ID</param>
        /// <param name="barcodeNumber">提取到的条码单号</param>
        /// <param name="barcodeType">条码类型</param>
        /// <param name="barcodeConfidence">识别置信度</param>
        /// <param name="parseDurationMs">PDF解析花费的时间（毫秒）</param>
        /// <returns>操作是否成功</returns>
        public async Task<bool> SaveCacheAsync(string waybillNumber, byte[] pdfBytes, int pageCount, int fileSize, 
            string? originalUrl = null,
            string? finalMileTrackingNumber = null, int? customerId = null,
            string? barcodeNumber = null, byte barcodeType = 0, int? barcodeConfidence = null, int? parseDurationMs = null)
        {
            try
            {
                var existingCache = await _cacheRepository.GetByWaybillNumberAsync(waybillNumber);
                if (existingCache == null)
                {
                    var newCache = new LabelPdfCache
                    {
                        NeutralWaybillNumber = waybillNumber,
                        PdfBytes = pdfBytes,
                        PageCount = pageCount,
                        FileSize = fileSize,
                        OriginalUrl = originalUrl,
                        Status = 1,
                        RetryCount = 0,
                        ErrorMessage = null,
                        FinalMileTrackingNumber = finalMileTrackingNumber,
                        CustomerId = customerId,
                        BarcodeNumber = barcodeNumber,
                        BarcodeType = barcodeType,
                        BarcodeConfidence = barcodeConfidence,
                        BarcodeExtractTime = !string.IsNullOrEmpty(barcodeNumber) ? DateTime.UtcNow : null,
                        ParseDurationMs = parseDurationMs
                    };
                    await _cacheRepository.CreateAsync(newCache);
                }
                else
                {
                    existingCache.PdfBytes = pdfBytes;
                    existingCache.PageCount = pageCount;
                    existingCache.FileSize = fileSize;
                    existingCache.OriginalUrl = originalUrl ?? existingCache.OriginalUrl;
                    existingCache.Status = 1;
                    existingCache.RetryCount = 0;
                    existingCache.ErrorMessage = null;
                    existingCache.FinalMileTrackingNumber = finalMileTrackingNumber ?? existingCache.FinalMileTrackingNumber;
                    existingCache.CustomerId = customerId ?? existingCache.CustomerId;
                    existingCache.ParseDurationMs = parseDurationMs ?? existingCache.ParseDurationMs;
                    if (!string.IsNullOrEmpty(barcodeNumber))
                    {
                        existingCache.BarcodeNumber = barcodeNumber;
                        existingCache.BarcodeType = barcodeType;
                        existingCache.BarcodeConfidence = barcodeConfidence;
                        existingCache.BarcodeExtractTime = DateTime.UtcNow;
                    }
                    await _cacheRepository.UpdateAsync(existingCache);
                }

                _logger.LogInformation("Successfully saved cache for waybill: {number}", waybillNumber);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error saving cache for waybill: {number}", waybillNumber);
                return false;
            }
        }

        /// <summary>
        /// 标记缓存为失效状态
        /// </summary>
        /// <param name="waybillNumber">中性面单单号</param>
        /// <returns>操作是否成功</returns>
        public async Task<bool> InvalidateCacheAsync(string waybillNumber)
        {
            try
            {
                return await _cacheRepository.InvalidateCacheAsync(waybillNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error invalidating cache for waybill: {number}", waybillNumber);
                return false;
            }
        }

        /// <summary>
        /// 处理单条缓存任务（公开接口，用于手动触发）
        /// </summary>
        /// <param name="waybillNumber">中性面单单号</param>
        /// <returns>处理是否成功</returns>
        /// <summary>
        /// 处理单个缓存任务（公开接口）
        /// </summary>
        /// <param name="waybillNumber">订单单号</param>
        /// <returns>(是否成功, 错误消息)</returns>
        public async Task<(bool Success, string ErrorMessage)> ProcessSingleCacheTaskAsync(string waybillNumber)
        {
            return await ProcessSingleCacheTask(waybillNumber);
        }

        /// <summary>
        /// 获取缓存统计信息
        /// </summary>
        /// <returns>统计数据</returns>
        public async Task<CacheStatistics> GetCacheStatisticsAsync()
        {
            try
            {
                var db = _cacheRepository.GetClient();
                
                var durations = await db.Queryable<LabelPdfCache>()
                    .Where(c => c.ParseDurationMs.HasValue)
                    .Select(c => c.ParseDurationMs.Value)
                    .ToListAsync();

                var stats = new CacheStatistics
                {
                    TotalRecords = await db.Queryable<LabelPdfCache>().CountAsync(),
                    SuccessRecords = await db.Queryable<LabelPdfCache>().Where(c => c.Status == 1).CountAsync(),
                    FailedRecords = await db.Queryable<LabelPdfCache>().Where(c => c.Status == 2).CountAsync(),
                    InvalidRecords = await db.Queryable<LabelPdfCache>().Where(c => c.Status == 3).CountAsync(),
                    PendingRecords = await db.Queryable<LabelPdfCache>().Where(c => c.Status == 0).CountAsync(),
                    WithBarcodeRecords = await db.Queryable<LabelPdfCache>().Where(c => !string.IsNullOrEmpty(c.BarcodeNumber)).CountAsync(),
                    AverageParseDurationMs = durations.Any() ? (int)durations.Average() : 0,
                    MaxParseDurationMs = durations.Any() ? durations.Max() : 0,
                    MinParseDurationMs = durations.Any() ? durations.Min() : 0,
                };

                _logger.LogInformation("Cache statistics: Total={total}, Success={success}, Failed={failed}, Invalid={invalid}, Pending={pending}, WithBarcode={barcode}",
                    stats.TotalRecords, stats.SuccessRecords, stats.FailedRecords, stats.InvalidRecords, stats.PendingRecords, stats.WithBarcodeRecords);

                return stats;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting cache statistics");
                throw;
            }
        }

        /// <summary>
        /// 处理待处理的缓存任务
        /// </summary>
        /// <param name="maxRetryCount">最大重试次数，默认3次</param>
        /// <param name="batchSize">每次处理的批量大小，默认300</param>
        /// <returns>处理成功的数量</returns>
        public async Task<int> ProcessPendingTasksAsync(int maxRetryCount = 3, int batchSize = 300)
        {
            var successCount = 0;
            try
            {
                _logger.LogInformation("Starting to process pending PDF cache tasks, batch size: {size}", batchSize);

                // 第一步：处理失效的缓存
                var invalidCaches = await _cacheRepository.GetInvalidCachesAsync(batchSize);
                foreach (var cache in invalidCaches)
                {
                    if ((await ProcessSingleCacheTask(cache.NeutralWaybillNumber, cache)).Success)
                    {
                        successCount++;
                    }
                }

                // 第二步：处理待处理的任务
                var remainingBatchSize = batchSize - invalidCaches.Count;
                var pendingTasks = await _cacheRepository.GetPendingTasksAsync(maxRetryCount, remainingBatchSize);
                foreach (var task in pendingTasks)
                {
                    if ((await ProcessSingleCacheTask(task.NeutralWaybillNumber, task)).Success)
                    {
                        successCount++;
                    }
                }

                // 第三步：处理订单表中新的有标签订单（缓存表中不存在的）
                // 仅处理创建时间>=2026-05-10的订单
                var newBatchSize = remainingBatchSize - pendingTasks.Count;
                if (newBatchSize > 0)
                {
                    var newOrders = await _cacheRepository.GetNewOrdersWithLabelsForBackgroundTaskAsync(newBatchSize);
                    foreach (var waybillNumber in newOrders)
                    {
                        if ((await ProcessSingleCacheTask(waybillNumber)).Success)
                        {
                            successCount++;
                        }
                    }
                }

                _logger.LogInformation("Completed processing PDF cache tasks, total processed: {count}, invalid: {invalidCount}, pending: {pendingCount}, new orders: {newCount}",
                    successCount, invalidCaches.Count, pendingTasks.Count, (remainingBatchSize - pendingTasks.Count));
                return successCount;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing pending cache tasks");
                return successCount;
            }
        }

        #region 私有方法
        /// <summary>
        /// 处理单个缓存任务
        /// </summary>
        /// <param name="waybillNumber">订单单号</param>
        /// <param name="existingCache">已存在的缓存记录</param>
        /// <returns>(是否成功, 错误消息)</returns>
        private async Task<(bool Success, string ErrorMessage)> ProcessSingleCacheTask(string waybillNumber, LabelPdfCache? existingCache = null)
        {
            var startTime = DateTime.UtcNow;
            try
            {
                _logger.LogInformation("Processing cache task for waybill: {number}", waybillNumber);

                // 获取订单信息
                var order = await _labelReplaceRepository.GetByWaybillNumberAsync(waybillNumber);
                if (order == null || string.IsNullOrEmpty(order.Label))
                {
                    _logger.LogWarning("No order or label found for waybill: {number}", waybillNumber);
                    await UpdateCacheStatus(existingCache, waybillNumber, 2, "无订单或标签数据", existingCache?.RetryCount + 1 ?? 0);
                    return (false, "无订单或标签数据");
                }

                byte[] labelBytes;
                // 解析Label内容
                if (order.Label.StartsWith("data:"))
                {
                    // 处理base64 data URL
                    var base64Data = order.Label.Substring(order.Label.IndexOf(",") + 1);
                    labelBytes = Convert.FromBase64String(base64Data);
                }
                else if (order.Label.StartsWith("http://") || order.Label.StartsWith("https://"))
                {
                    // 处理URL，下载PDF
                    using var httpClient = _httpClientFactory.CreateClient();
                    httpClient.Timeout = TimeSpan.FromSeconds(PdfDownloadTimeoutSeconds);
                    labelBytes = await httpClient.GetByteArrayAsync(order.Label);
                }
                else
                {
                    // 纯base64编码
                    labelBytes = Convert.FromBase64String(order.Label);
                }

                // 当labelBytes为null或为空时，标记为失败（源文件有问题）
                if (labelBytes == null || labelBytes.Length == 0)
                {
                    var duration = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                    _logger.LogError("labelBytes is null or empty for waybill: {number}, duration: {duration}ms - 源文件有问题", waybillNumber, duration);
                    var newRetryCount = (existingCache?.RetryCount ?? 0) + 1;
                    await UpdateCacheStatus(existingCache, waybillNumber, 2, "源文件为空或无效，无法提取条码", newRetryCount, duration);
                    return (false, "源文件为空或无效，无法提取条码");
                }

                // 校验PDF页数
                int pageCount = GetPdfPageCount(labelBytes);
                if (pageCount > 1)
                {
                    var duration = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                    _logger.LogWarning("PDF page count exceeded for waybill: {number}, pages: {count}, duration: {duration}ms", waybillNumber, pageCount, duration);
                    await UpdateCacheStatus(existingCache, waybillNumber, 2, $"PDF页数超过1页，实际页数：{pageCount}", MaxRetryCount, duration);
                    return (false, $"PDF页数超过1页，实际页数：{pageCount}页");
                }

                // 校验文件大小
                if (labelBytes.Length > MaxFileSizeBytes)
                {
                    var duration = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;
                    _logger.LogWarning("PDF file size too large for waybill: {number}, size: {size}, duration: {duration}ms", waybillNumber, labelBytes.Length, duration);
                    await UpdateCacheStatus(existingCache, waybillNumber, 2, $"文件大小超过限制，实际大小：{labelBytes.Length}字节", MaxRetryCount, duration);
                    return (false, $"文件大小超过限制，实际大小：{labelBytes.Length}字节");
                }

                // 提取条码信息
                var (barcodeNumber, barcodeType, barcodeConfidence) = await ExtractBarcodeFromPdfAsync(labelBytes);
                var parseDurationMs = (int)(DateTime.UtcNow - startTime).TotalMilliseconds;

                // 保存缓存（包含关联信息和条码信息）
                await SaveCacheAsync(
                    waybillNumber: waybillNumber,
                    pdfBytes: labelBytes,
                    pageCount: pageCount,
                    fileSize: labelBytes.Length,
                    originalUrl: order.Label,
                    finalMileTrackingNumber: order.FinalMileTrackingNumber,
                    customerId: order.CustomerId,
                    barcodeNumber: barcodeNumber,
                    barcodeType: barcodeType,
                    barcodeConfidence: barcodeConfidence,
                    parseDurationMs: parseDurationMs);
                    
                return (true, string.Empty);
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "HTTP error downloading label for waybill: {number}", waybillNumber);
                var newRetryCount = (existingCache?.RetryCount ?? 0) + 1;
                var status = newRetryCount >= MaxRetryCount ? (byte)2 : (byte)0; // 达到最大重试次数标记为失败，否则继续待处理
                await UpdateCacheStatus(existingCache, waybillNumber, status, $"下载失败：{ex.Message}", newRetryCount);
                return (false, $"下载失败：{ex.Message}");
            }
            catch (System.FormatException ex)
            {
                _logger.LogError(ex, "Base64 format error for waybill: {number}", waybillNumber);
                await UpdateCacheStatus(existingCache, waybillNumber, 2, $"base64格式错误：{ex.Message}", MaxRetryCount); // 格式错误不需要重试
                return (false, $"base64格式错误：{ex.Message}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing cache task for waybill: {number}", waybillNumber);
                var newRetryCount = (existingCache?.RetryCount ?? 0) + 1;
                var status = newRetryCount >= MaxRetryCount ? (byte)2 : (byte)0;
                await UpdateCacheStatus(existingCache, waybillNumber, status, $"处理失败：{ex.Message}", newRetryCount);
                return (false, $"处理失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新缓存状态
        /// </summary>
        private async Task UpdateCacheStatus(LabelPdfCache? existingCache, string waybillNumber, byte status, string errorMessage, int retryCount, int? parseDurationMs = null)
        {
            try
            {
                if (existingCache == null)
                {
                    existingCache = new LabelPdfCache
                    {
                        NeutralWaybillNumber = waybillNumber,
                        Status = status,
                        ErrorMessage = errorMessage,
                        RetryCount = retryCount,
                        LastRetryTime = DateTime.UtcNow,
                        ParseDurationMs = parseDurationMs
                    };
                    await _cacheRepository.CreateAsync(existingCache);
                }
                else
                {
                    existingCache.Status = status;
                    existingCache.ErrorMessage = errorMessage;
                    existingCache.RetryCount = retryCount;
                    existingCache.LastRetryTime = DateTime.UtcNow;
                    if (parseDurationMs.HasValue)
                    {
                        existingCache.ParseDurationMs = parseDurationMs.Value;
                    }
                    await _cacheRepository.UpdateAsync(existingCache);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating cache status for waybill: {number}", waybillNumber);
            }
        }

        /// <summary>
        /// 获取PDF页数
        /// </summary>
        private int GetPdfPageCount(byte[] pdfBytes)
        {
            using var document = PdfReader.Open(new MemoryStream(pdfBytes), PdfDocumentOpenMode.Import);
            return document.PageCount;
        }
        /// <summary>
        /// 从PDF字节流中提取条码信息
        /// </summary>
        /// <param name="pdfBytes">PDF字节流</param>
        /// <returns>元组：(条码内容, 条码类型:0=未识别,1=一维码,2=二维码, 置信度0-100)</returns>
        public async Task<(string barcodeNumber, byte barcodeType, int confidence)> ExtractBarcodeFromPdfAsync(byte[] pdfBytes)
        {
            try
            {
                _logger.LogInformation("Starting barcode extraction from PDF");
                
                // 使用DinkToPdf将PDF第一页转为图片
                Bitmap? pdfBitmap = null;
                try
                {
                    pdfBitmap = ConvertPdfFirstPageToBitmap(pdfBytes);
                    if (pdfBitmap == null)
                    {
                        _logger.LogWarning("Failed to convert PDF to bitmap");
                        return (string.Empty, 0, 0);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Error converting PDF to bitmap");
                    return (string.Empty, 0, 0);
                }

                using (pdfBitmap)
                {
                    var watch = System.Diagnostics.Stopwatch.StartNew();
                    
                    // 调试：保存原始PDF位图到桌面便于排查
                    //SaveDebugImage(pdfBitmap, "pdf_original");
                    
                    // 先尝试识别二维码（物流面单最常见）
                    var qrResult = await RecognizeBarcodeAsync(pdfBitmap, BarcodeFormat.QR_CODE, "QR");
                    if (qrResult.text != null && qrResult.text.Length > 200)
                        qrResult.text = string.Empty;
                    if (!string.IsNullOrEmpty(qrResult.text))
                    {
                        watch.Stop();
                        _logger.LogInformation("Successfully extracted QR code: {code}, confidence: {confidence}%, took: {ms}ms", 
                            qrResult.text, qrResult.confidence, watch.ElapsedMilliseconds);
                        return (qrResult.text, 2, qrResult.confidence);
                    }

                    // 二维码识别失败，尝试识别CODE128一维码（物流行业标准）
                    var code128Result = await RecognizeBarcodeAsync(pdfBitmap, BarcodeFormat.CODE_128, "CODE128");
                    if (code128Result.text != null && code128Result.text.Length > 200)
                        code128Result.text = string.Empty;
                    if (!string.IsNullOrEmpty(code128Result.text))
                    {
                        watch.Stop();
                        _logger.LogInformation("Successfully extracted CODE128 barcode: {code}, confidence: {confidence}%, took: {ms}ms", 
                            code128Result.text, code128Result.confidence, watch.ElapsedMilliseconds);
                        return (code128Result.text, 1, code128Result.confidence);
                    }

                    // 尝试其他常见一维码格式
                    //var otherFormats = new[] { BarcodeFormat.CODE_39, BarcodeFormat.CODE_93, BarcodeFormat.EAN_13, BarcodeFormat.UPC_A };
                    //var other1DResult = await RecognizeBarcodeAsync(pdfBitmap, otherFormats, "1D_Others");
                    //if (other1DResult.text != null && other1DResult.text.Length > 200)
                    //    other1DResult.text = string.Empty;
                    //if (!string.IsNullOrEmpty(other1DResult.text))
                    //{
                    //    watch.Stop();
                    //    _logger.LogInformation("Successfully extracted 1D barcode: {code}, confidence: {confidence}%, took: {ms}ms", 
                    //        other1DResult.text, other1DResult.confidence, watch.ElapsedMilliseconds);
                    //    return (other1DResult.text, 1, other1DResult.confidence);
                    //}

                    watch.Stop();
                    _logger.LogDebug("No barcode found in PDF, took: {ms}ms", watch.ElapsedMilliseconds);
                    return (string.Empty, 0, 0);
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Error extracting barcode from PDF");
                return (string.Empty, 0, 0);
            }
        }

        /// <summary>
        /// 将PDF第一页转换为Bitmap图像
        /// </summary>
        /// <param name="pdfBytes">PDF字节流</param>
        /// <returns>转换后的Bitmap图像，如失败返回null</returns>
        private Bitmap? ConvertPdfFirstPageToBitmap(byte[] pdfBytes)
        {
            try
            {
                var tempPdfPath = Path.Combine(Path.GetTempPath(), $"pdf_{Guid.NewGuid()}.pdf");
                
                try
                {
                    File.WriteAllBytes(tempPdfPath, pdfBytes);
                    
                    var rasterizer = new GhostscriptRasterizer();
                    
                    rasterizer.Open(tempPdfPath);
                    
                    Image renderedImage = rasterizer.GetPage(200, 1);
                    
                    var bitmap = new Bitmap(renderedImage);
                    
                    rasterizer.Close();
                    
                    _logger.LogDebug("Successfully rendered PDF to bitmap using GhostScript, size: {width}x{height}", 
                        bitmap.Width, bitmap.Height);
                    
                    return bitmap;
                }
                finally
                {
                    if (File.Exists(tempPdfPath))
                    {
                        try
                        {
                            File.Delete(tempPdfPath);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogDebug(ex, "Failed to delete temporary PDF file: {path}", tempPdfPath);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error converting PDF to bitmap using GhostScript");
                return null;
            }
        }

        /// <summary>
        /// 识别指定格式的条码
        /// </summary>
        /// <param name="bitmap">图片位图</param>
        /// <param name="formats">要识别的条码格式列表</param>
        /// <param name="debugLabel">调试标签，用于保存不同格式的识别图像</param>
        /// <returns>元组：(识别文本, 置信度0-100)</returns>
        private async Task<(string text, int confidence)> RecognizeBarcodeAsync(Bitmap bitmap, BarcodeFormat format, string debugLabel)
        {
            return await RecognizeBarcodeAsync(bitmap, new[] { format }, debugLabel);
        }

        /// <summary>
        /// 识别指定格式的条码
        /// </summary>
        /// <param name="bitmap">图片位图</param>
        /// <param name="formats">要识别的条码格式列表</param>
        /// <param name="debugLabel">调试标签，用于保存不同格式的识别图像</param>
        /// <returns>元组：(识别文本, 置信度0-100)</returns>
        private async Task<(string text, int confidence)> RecognizeBarcodeAsync(Bitmap bitmap, BarcodeFormat[] formats, string debugLabel)
        {
            return await Task.Run(() =>
            {
                try
                {
                    // 调试：为每种条码格式保存识别图像到桌面便于排查
                    //SaveDebugImage(bitmap, $"barcode_{debugLabel}");
                    
                    // 将Bitmap转换为灰度数组用于条码识别
                    var luminanceSource = new BitmapLuminanceSource(bitmap);
                    var hybridBinarizer = new HybridBinarizer(luminanceSource);
                    var binBitmap = new BinaryBitmap(hybridBinarizer);

                    // 创建条码读取器，优化参数适配物流面单场景
                    var hints = new Dictionary<DecodeHintType, object>
                    {
                        { DecodeHintType.TRY_HARDER, true },
                        { DecodeHintType.PURE_BARCODE, false }
                    };

                    var reader = new MultiFormatReader { Hints = hints };

                    // 执行识别
                    ZXing.Result result = null;
                    if (formats.Length > 0)
                    {
                        var formatList = new System.Collections.Generic.List<BarcodeFormat>(formats);
                        hints[DecodeHintType.POSSIBLE_FORMATS] = formatList;
                        result = reader.decode(binBitmap);
                    }
                    else
                    {
                        result = reader.decode(binBitmap);
                    }

                    if (result != null && !string.IsNullOrEmpty(result.Text))
                    {
                        // 计算置信度：基于结果点数量评估
                        int confidence = CalculateConfidence(result);
                        _logger.LogDebug("Barcode recognized [{type}]: {text}, format: {format}, confidence: {confidence}%", 
                            debugLabel, result.Text, result.BarcodeFormat, confidence);
                        return (result.Text, confidence);
                    }

                    _logger.LogDebug("No barcode recognized for type [{type}] in image (bitmap: {width}x{height})", 
                        debugLabel, bitmap.Width, bitmap.Height);
                    return (string.Empty, 0);
                }
                catch (Exception ex)
                {
                    _logger.LogDebug(ex, "Barcode recognition failed for type [{type}], formats: {formats}", 
                        debugLabel, string.Join(",", formats));
                    return (string.Empty, 0);
                }
            });
        }

        /// <summary>
        /// 保存调试图像到桌面
        /// </summary>
        /// <param name="bitmap">要保存的位图</param>
        /// <param name="label">标签，用于区分不同类型的调试图像</param>
        private void SaveDebugImage(Bitmap bitmap, string label)
        {
            try
            {
                var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                var debugImagePath = Path.Combine(desktopPath, $"debug_{label}_{DateTime.Now:yyyyMMdd_HHmmss}.png");
                bitmap.Save(debugImagePath, System.Drawing.Imaging.ImageFormat.Png);
                _logger.LogInformation("Debug image [{label}] saved to: {path}", label, debugImagePath);
            }
            catch (Exception ex)
            {
                _logger.LogDebug(ex, "Failed to save debug image [{label}]", label);
            }
        }

        /// <summary>
        /// Bitmap转换为LuminanceSource的辅助类
        /// </summary>
        private class BitmapLuminanceSource : LuminanceSource
        {
            private readonly byte[] _luminances;

            public BitmapLuminanceSource(Bitmap bitmap) : base(bitmap.Width, bitmap.Height)
            {
                _luminances = new byte[Width * Height];
                ConvertBitmapToLuminances(bitmap);
            }

            private void ConvertBitmapToLuminances(Bitmap bitmap)
            {
                int offset = 0;
                for (int y = 0; y < Height; y++)
                {
                    for (int x = 0; x < Width; x++)
                    {
                        var pixel = bitmap.GetPixel(x, y);
                        // 计算灰度值：标准公式 0.299R + 0.587G + 0.114B
                        byte luminance = (byte)((pixel.R * 0.299) + (pixel.G * 0.587) + (pixel.B * 0.114));
                        _luminances[offset++] = luminance;
                    }
                }
            }

            public override byte[] getRow(int y, byte[] row)
            {
                if (row == null || row.Length < Width)
                {
                    row = new byte[Width];
                }
                Array.Copy(_luminances, y * Width, row, 0, Width);
                return row;
            }

            public override byte[] Matrix => _luminances;
        }

        /// <summary>
        /// 计算条码识别的置信度
        /// </summary>
        /// <param name="result">ZXing识别结果</param>
        /// <returns>置信度0-100</returns>
        private int CalculateConfidence(ZXing.Result result)
        {
            // 基于识别结果的特征计算置信度
            // 基础分数为70分，根据结果点数量增加
            int baseConfidence = 70;
            
            if (result.ResultPoints != null && result.ResultPoints.Length > 0)
            {
                // 每个识别点增加5分，最多100分
                int pointBonus = Math.Min(result.ResultPoints.Length * 5, 30);
                return Math.Min(baseConfidence + pointBonus, 100);
            }

            return baseConfidence;
        }
        #endregion
    }
}
