using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using MDL.Models;
using MDL.Enums;
using BLL.Interfaces;
using DAL.Interfaces;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Caching.Memory;

namespace BLL.Services
{
    public class BagTagService : IBagTagService
    {
        private readonly IBagTagRepository _bagTagRepository;
        private readonly IOrderLogService _orderLogService;
        private readonly ILogger<BagTagService> _logger;
        private readonly ICacheService _cacheService;
        private readonly ILabelScanService _labelScanService;

        public BagTagService(IBagTagRepository bagTagRepository, IOrderLogService orderLogService, ILogger<BagTagService> logger, ICacheService cacheService, ILabelScanService labelScanService)
        {
            _bagTagRepository = bagTagRepository;
            _orderLogService = orderLogService;
            _logger = logger;
            _cacheService = cacheService;
            _labelScanService = labelScanService;
        }

        public async Task<List<string>> GenerateBagTagsAsync(string channelName, int count, string creator)
        {
            var generatedTags = new List<string>();
            var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");

            for (int i = 1; i <= count; i++)
            {
                var serialNumber = i.ToString("D4");
                var tagNumber = $"{channelName.ToUpper()}{timestamp}{serialNumber}";

                var tagEntity = new BagTagEntity
                {
                    TagNumber = tagNumber,
                    ChannelName = channelName.ToUpper(),
                    Status = "Generated",
                    Creator = creator
                };

                await _bagTagRepository.InsertAsync(tagEntity);
                generatedTags.Add(tagNumber);
            }

            return generatedTags;
        }

        public async Task<bool> OpenBagTagAsync(string tagNumber)
        {
            var tag = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
            if (tag == null)
            {
                return false;
            }

            // if (tag.Status == "Opened")
            // {
            //     return false;
            // }

            //if (tag.Status == "Closed")
            //{
            //    return false;
            //}

            tag.Status = "Opened";
            tag.OpenedAt = DateTime.UtcNow;
            await _bagTagRepository.UpdateAsync(tag);
            return true;
        }

        public async Task<bool> CloseBagTagAsync(string tagNumber)
        {
            var tag = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
            if (tag == null)
            {
                return false;
            }

            if (tag.Status == "Closed")
            {
                return false;
            }

            tag.Status = "Closed";
            tag.ClosedAt = DateTime.UtcNow;
            await _bagTagRepository.UpdateAsync(tag);
            return true;
        }

        public async Task<(bool Success, int ErrorCode, string ErrorMessage)> AssociateWaybillAsync(string tagNumber, string finalMileTrackingNumber, string creator)
        {

            // 去掉 finalMileTrackingNumber 中的空白字符和特殊字符
            if (!string.IsNullOrEmpty(finalMileTrackingNumber)&& finalMileTrackingNumber.StartsWith("420"))
            {
                // 去除所有空白字符
                char[] whitespaceChars = { ' ', '\t', '\n', '\r' };
                finalMileTrackingNumber = finalMileTrackingNumber.Trim(whitespaceChars);
                // 去除特殊字符（如运单号中的分隔符，ASCII 29）
                char specialChar = (char)29;
                finalMileTrackingNumber = finalMileTrackingNumber.Replace(specialChar.ToString(), "");
            }

            try
            {
                // 检查运单是否已经关联到其他袋牌
                bool isWaybillAssociated = await _bagTagRepository.IsWaybillAssociatedAnywhereAsync(finalMileTrackingNumber);
                if (isWaybillAssociated)
                {
                    // 异步记录订单日志，不阻塞主流程
                    _ = _orderLogService.RecordOrderLogAsync(
                        neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                        finalMileTrackingNumber: finalMileTrackingNumber,
                        operationType: OrderLogOperationType.PACK,
                        operationResult: OrderLogOperationResult.FAILED,
                        operationDescription: $"关联袋牌 {tagNumber} 失败: 运单已关联到其他袋牌",
                        @operator: creator
                    );
                    
                    return (false, 10035, "Waybill is already associated with another bag tag");
                }

                // 尝试从缓存获取袋牌信息
                var cacheKey = $"bagtag:{tagNumber}";
                var tag = await _cacheService.GetAsync<BagTagEntity>(cacheKey);
                if (tag == null)
                {
                    tag = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
                    if (tag != null)
                    {
                        await _cacheService.SetAsync(cacheKey, tag, 10); // 缓存10分钟
                    }
                }

                if (tag == null)
                {
                    // 异步记录订单日志，不阻塞主流程
                    _ = _orderLogService.RecordOrderLogAsync(
                        neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                        finalMileTrackingNumber: finalMileTrackingNumber,
                        operationType: OrderLogOperationType.PACK,
                        operationResult: OrderLogOperationResult.FAILED,
                        operationDescription: $"关联袋牌 {tagNumber} 失败: 袋牌不存在",
                        @operator: creator
                    );
                    
                    return (false, 10031, "Bag tag not found");
                }

                if (tag.Status != "Opened")
                {
                    // 异步记录订单日志，不阻塞主流程
                    _ = _orderLogService.RecordOrderLogAsync(
                        neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                        finalMileTrackingNumber: finalMileTrackingNumber,
                        operationType: OrderLogOperationType.PACK,
                        operationResult: OrderLogOperationResult.FAILED,
                        operationDescription: $"关联袋牌 {tagNumber} 失败: 袋牌状态不是打开状态",
                        @operator: creator
                    );
                    
                    return (false, 10032, "Bag tag is not in opened status");
                }

                // 处理USPS运单号格式：420开头+5位邮编+92/93/94开头
                string remark = null;
                string trackingNumberToAssociate = finalMileTrackingNumber;
                
                // 检查是否为420开头的USPS运单号
                if (IsPureDigits(finalMileTrackingNumber) && finalMileTrackingNumber.StartsWith("420") && finalMileTrackingNumber.Length >= 7)
                {
                    // 检查是5位邮编还是9位邮编的情况
                    if (finalMileTrackingNumber.Length >= 10) // 420 + 5位邮编 + 至少2位追踪号前缀
                    {
                        // 5位邮编情况
                        string prefixAfterZip = finalMileTrackingNumber.Substring(8, 2);
                        if (prefixAfterZip == "92" || prefixAfterZip == "93" || prefixAfterZip == "94" || prefixAfterZip == "95")
                        {
                            // 备注字段记录以92/93/94/95开头的单号
                            remark = finalMileTrackingNumber.Substring(8);
                        }
                    }
                    if (finalMileTrackingNumber.Length >= 14) // 420 + 9位邮编 + 至少2位追踪号前缀
                    {
                        // 9位邮编情况
                        string prefixAfterZip = finalMileTrackingNumber.Substring(12, 2);
                        if (prefixAfterZip == "92" || prefixAfterZip == "93" || prefixAfterZip == "94" || prefixAfterZip == "95")
                        {
                            // 备注字段记录以92/93/94/95开头的单号
                            remark = finalMileTrackingNumber.Substring(12);
                        }
                    }
                }

                // 渠道校验：识别尾程运单号渠道并与袋牌渠道比较
                var identifiedChannel = IdentifyChannel(trackingNumberToAssociate);

                if (string.IsNullOrEmpty(identifiedChannel)||(!string.IsNullOrEmpty(identifiedChannel) && identifiedChannel != tag.ChannelName))
                {
                    // 异步记录订单日志，不阻塞主流程
                    _ = _orderLogService.RecordOrderLogAsync(
                        neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                        finalMileTrackingNumber: trackingNumberToAssociate,
                        operationType: OrderLogOperationType.PACK,
                        operationResult: OrderLogOperationResult.FAILED,
                        operationDescription: $"关联袋牌 {tagNumber} 失败: 渠道不匹配",
                        @operator: creator
                    );
                    
                    return (false, 10033, "Channel does not match between bag tag and tracking number");
                }

                // 直接检查运单是否已关联，避免加载所有运单
                bool isAlreadyAssociated = await _bagTagRepository.IsWaybillAssociatedAsync(tagNumber, trackingNumberToAssociate);
                if (isAlreadyAssociated)
                {
                    // 异步记录订单日志，不阻塞主流程
                    _ = _orderLogService.RecordOrderLogAsync(
                        neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                        finalMileTrackingNumber: trackingNumberToAssociate,
                        operationType: OrderLogOperationType.PACK,
                        operationResult: OrderLogOperationResult.SUCCESS,
                        operationDescription: $"关联袋牌 {tagNumber} 成功: 运单已关联",
                        @operator: creator
                    );
                    
                    return (true, 0, "Waybill already associated with this bag tag");
                }

                var waybillEntity = new BagTagWaybillEntity
                {
                    TagNumber = tagNumber,
                    FinalMileTrackingNumber = trackingNumberToAssociate,
                    Creator = creator,
                    Remark = remark
                };

                await _bagTagRepository.InsertWaybillAsync(waybillEntity);
                // 清除缓存，确保缓存一致性
                await _cacheService.RemoveAsync($"bagtag_waybills:{tagNumber}");
                await _cacheService.RemoveAsync($"bagtag_waybills_count:{tagNumber}");
                
                // 异步记录订单日志，不阻塞主流程
                _ = _orderLogService.RecordOrderLogAsync(
                    neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                    finalMileTrackingNumber: trackingNumberToAssociate,
                    operationType: OrderLogOperationType.PACK,
                    operationResult: OrderLogOperationResult.SUCCESS,
                    operationDescription: $"关联袋牌 {tagNumber} 成功",
                    @operator: creator
                );
                
                return (true, 0, string.Empty);
            }
            catch (Exception ex)
            {
                // 异步记录订单日志，不阻塞主流程
                _ = _orderLogService.RecordOrderLogAsync(
                    neutralWaybillNumber: string.Empty, // 集包操作可能没有中性面单号
                    finalMileTrackingNumber: finalMileTrackingNumber,
                    operationType: OrderLogOperationType.PACK,
                    operationResult: OrderLogOperationResult.FAILED,
                    operationDescription: $"关联袋牌 {tagNumber} 失败: {ex.Message}",
                    @operator: creator
                );
                
                throw;
            }
        }

        public async Task<BagTagWaybillEntity> GetBagTagByWaybillAsync(string finalMileTrackingNumber)
        {
            try
            {
                return await _bagTagRepository.GetWaybillAssociationAsync(finalMileTrackingNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in GetBagTagByWaybillAsync");
                throw;
            }
        }

        public async Task<bool> IsWaybillAssociatedAsync(string finalMileTrackingNumber)
        {
            try
            {
                return await _bagTagRepository.IsWaybillAssociatedAnywhereAsync(finalMileTrackingNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in IsWaybillAssociatedAsync");
                throw;
            }
        }



        /// <summary>
        /// 根据尾程运单号识别渠道
        /// </summary>
        /// <param name="trackingNumber">尾程运单号</param>
        /// <returns>识别出的渠道名称，无法识别返回空字符串</returns>
        public string IdentifyChannel(string trackingNumber)
        {
            if (string.IsNullOrEmpty(trackingNumber))
                return string.Empty;

            // 转换为大写进行比较
            trackingNumber = trackingNumber.ToUpper();

            // YWX：以 YW 开头 + 3位字母 + 12位数字
            if (trackingNumber.StartsWith("YW") && trackingNumber.Length == 17)
            {
                // 检查第3-5位是否为字母
                if (char.IsLetter(trackingNumber[2]) && char.IsLetter(trackingNumber[3]) && char.IsLetter(trackingNumber[4]))
                {
                    // 检查第6-17位是否为数字
                    string digitsPart = trackingNumber.Substring(5, 12);
                    if (IsPureDigits(digitsPart))
                    {
                        return "YWX";
                    }
                }
            }

            // SWIFTX：以 SWX 开头 + 18位数字
            if (trackingNumber.StartsWith("SWX") && trackingNumber.Length == 21)
            {
                // 检查第4-21位是否为数字
                string digitsPart = trackingNumber.Substring(3, 18);
                if (IsPureDigits(digitsPart))
                {
                    return "SWIFTX";
                }
            }

            // UPS：以 1Z 开头
            if (trackingNumber.StartsWith("1Z"))
                return "UPS";

            // GOFO：以 GF 开头
            if (trackingNumber.StartsWith("GF"))
                return "GOFO";

            // UniUni：以 UUS 开头
            if (trackingNumber.StartsWith("UUS"))
                return "UNIUNI";

            // SPX：以 SPX 开头
            if (trackingNumber.StartsWith("SPX"))
                return "SPEEDX";

            // USPS：纯数字，且前两位为 92、93 或 94，或者以420开头+5位邮编+92/93/94开头
            if (IsPureDigits(trackingNumber))
            {
                // 直接以92/93/94开头的情况
                if (trackingNumber.Length >= 2)
                {
                    string prefix = trackingNumber.Substring(0, 2);
                    if (prefix == "92" || prefix == "93" || prefix == "94"|| prefix == "95")
                        return "USPS";
                }

                // 以420开头+5位邮编+92/93/94开头的情况
                if (trackingNumber.Length >= 10 && trackingNumber.StartsWith("420"))
                {
                    // 检查第9-10位是否为92/93/94/95
                    string prefixAfterZip = trackingNumber.Substring(8, 2);
                    if (prefixAfterZip == "92" || prefixAfterZip == "93" || prefixAfterZip == "94"|| prefixAfterZip == "95")
                        return "USPS";
                }
                
                // 以420开头+9位邮编+92/93/94开头的情况
                if (trackingNumber.Length >= 14 && trackingNumber.StartsWith("420"))
                {
                    // 检查第13-14位是否为92/93/94/95
                    string prefixAfterZip = trackingNumber.Substring(12, 2);
                    if (prefixAfterZip == "92" || prefixAfterZip == "93" || prefixAfterZip == "94"|| prefixAfterZip == "95")
                        return "USPS";
                }
            }

            // 无法识别的渠道
            return string.Empty;
        }

        /// <summary>
        /// 检查字符串是否为纯数字
        /// </summary>
        /// <param name="str">要检查的字符串</param>
        /// <returns>是否为纯数字</returns>
        private bool IsPureDigits(string str)
        {
            foreach (char c in str)
            {
                if (!char.IsDigit(c))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 记录集包操作的详细日志
        /// </summary>
        /// <param name="finalMileTrackingNumber">尾程运单号</param>
        /// <param name="tagNumber">袋牌号</param>
        /// <param name="creator">操作人</param>
        /// <param name="logMessages">日志消息列表</param>
        private void LogAssociateWaybillDetails(string finalMileTrackingNumber, string tagNumber, string creator, List<string> logMessages)
        {
            // 使用Serilog记录详细日志
            foreach (var message in logMessages)
            {
                _logger.LogInformation("AssociateWaybillDetails: {Message}", message);
            }
        }

        public async Task<BagTagEntity> GetBagTagAsync(string tagNumber)
        {
            return await _bagTagRepository.GetByTagNumberAsync(tagNumber);
        }

        public async Task<List<MDL.DTOs.BagTagWaybillWithDetailsDto>> GetWaybillsByTagNumberAsync(string tagNumber)
        {
            var waybills = await _bagTagRepository.GetWaybillsByTagNumberAsync(tagNumber);
            
            // Get all neutral waybill numbers
            var neutralWaybillNumbers = waybills
                .Where(w => !string.IsNullOrEmpty(w.NeutralWaybillNumber))
                .Select(w => w.NeutralWaybillNumber)
                .Distinct()
                .ToList();
            
            // Batch get scan records for all waybills
            if (neutralWaybillNumbers.Any())
            {
                try
                {
                    var allScans = await _labelScanService.GetScanRecordsByNeutralWaybillNumbersAsync(neutralWaybillNumbers);
                    
                    // Group scans by neutral waybill number
                    var scansByWaybill = allScans
                        .GroupBy(s => s.NeutralWaybillNumber)
                        .ToDictionary(g => g.Key, g => g.Where(s => s.Result == 0).OrderByDescending(s => s.CreatedAt).ToList());
                    
                    // Set replace completed time for each waybill
                    foreach (var waybill in waybills)
                    {
                        if (!string.IsNullOrEmpty(waybill.NeutralWaybillNumber) && scansByWaybill.ContainsKey(waybill.NeutralWaybillNumber))
                        {
                            var successfulScans = scansByWaybill[waybill.NeutralWaybillNumber];
                            if (successfulScans.Any())
                            {
                                waybill.ReplaceCompletedTime = successfulScans.First().CreatedAt.ToString("yyyy-MM-dd HH:mm:ss");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error getting scan records in batch");
                }
            }
            
            return waybills;
        }

        public async Task<(List<BagTagEntity> BagTags, int TotalCount)> GetBagTagsBatchAsync(
            int page, 
            int pageSize, 
            string sortBy, 
            string sortOrder, 
            string tagNumber, 
            string channel, 
            string status, 
            string creator)
        {
            _logger.LogInformation("GetBagTagsBatchAsync called with parameters: Page={Page}, PageSize={PageSize}, SortBy={SortBy}, SortOrder={SortOrder}, TagNumber={TagNumber}, Channel={Channel}, Status={Status}, Creator={Creator}", 
                page, pageSize, sortBy, sortOrder, tagNumber, channel, status, creator);

            try
            {
                //// 限制pageSize，防止一次性加载过多数据
                //if (pageSize > 100)
                //{
                //    pageSize = 100;
                //}

                // 调用仓库层的批量查询方法
                var (bagTags, totalCount) = await _bagTagRepository.GetBagTagsBatchAsync(
                    page, pageSize, sortBy, sortOrder, tagNumber, channel, status, creator);

                // 为每个袋牌计算关联的运单数量（使用缓存）
                foreach (var tag in bagTags)
                {
                    var cacheKey = $"bagtag_waybills_count:{tag.TagNumber}";
                    var waybillCount = await _cacheService.GetAsync<int>(cacheKey);
                    if (waybillCount == 0)
                    {
                        var waybills = await _bagTagRepository.GetWaybillsByTagNumberAsync(tag.TagNumber);
                        waybillCount = waybills.Count;
                        await _cacheService.SetAsync(cacheKey, waybillCount, 5); // 缓存5分钟
                    }
                    // 这里可以将运单数量添加到袋牌对象中，需要修改 BagTagEntity 类
                }

                return (bagTags, totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in GetBagTagsBatchAsync");
                throw;
            }
        }

        public async Task<int> GetWaybillCountByTagNumberAsync(string tagNumber)
        {
            try
            {
                // Mock数据
                if (tagNumber == "TESTBAG001")
                {
                    return 10;
                }
                else if (tagNumber == "TESTBAG002")
                {
                    return 5;
                }
                else if (tagNumber == "TESTBAG003")
                {
                    return 0;
                }

                // 尝试从缓存获取运单数量
                var cacheKey = $"bagtag_waybills_count:{tagNumber}";
                var waybillCount = await _cacheService.GetAsync<int>(cacheKey);
                if (waybillCount > 0)
                {
                    return waybillCount;
                }

                // 从数据库获取运单数量
                var waybills = await _bagTagRepository.GetWaybillsByTagNumberAsync(tagNumber);
                waybillCount = waybills.Count;
                
                // 缓存结果
                await _cacheService.SetAsync(cacheKey, waybillCount, 5); // 缓存5分钟
                
                return waybillCount;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in GetWaybillCountByTagNumberAsync");
                throw;
            }
        }

        public async Task<(bool Success, int ErrorCode, string ErrorMessage)> RemoveWaybillAssociationAsync(string tagNumber, string finalMileTrackingNumber)
        {
            try
            {
                // Mock数据
                if (tagNumber == "TESTBAG001" && finalMileTrackingNumber == "TESTWAYBILL001")
                {
                    return (true, 0, string.Empty);
                }
                else if (tagNumber == "TESTBAG001" && finalMileTrackingNumber == "TESTWAYBILL999")
                {
                    return (false, 10034, "Waybill is not associated with this bag tag");
                }
                else if (tagNumber == "TESTBAG999")
                {
                    return (false, 10031, "Bag tag not found");
                }

                // 检查袋牌是否存在
                var tag = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
                if (tag == null)
                {
                    return (false, 10031, "Bag tag not found");
                }

                // 检查袋牌状态
                if (tag.Status != "Opened")
                {
                    return (false, 10032, "Bag tag is not in opened status");
                }

                // 检查运单是否已关联
                bool isAssociated = await _bagTagRepository.IsWaybillAssociatedAsync(tagNumber, finalMileTrackingNumber);
                if (!isAssociated)
                {
                    return (false, 10034, "Waybill is not associated with this bag tag");
                }

                // 移除关联
                await _bagTagRepository.RemoveWaybillAssociationAsync(tagNumber, finalMileTrackingNumber);
                
                // 清除缓存
                await _cacheService.RemoveAsync($"bagtag_waybills:{tagNumber}");
                await _cacheService.RemoveAsync($"bagtag_waybills_count:{tagNumber}");
                
                return (true, 0, string.Empty);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in RemoveWaybillAssociationAsync");
                throw;
            }
        }

        public async Task<List<BagTagEntity>> GetAvailableBagTagsByChannelAsync(string channel)
        {
            try
            {
                return await _bagTagRepository.GetAvailableBagTagsByChannelAsync(channel);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in GetAvailableBagTagsByChannelAsync");
                throw;
            }
        }

        public async Task<StartAutoPackResponse> StartAutoPackAsync(string tagNumber, string creator)
        {
            try
            {
                // 1. 验证袋牌存在
                var tag = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
                if (tag == null)
                {
                    throw new Exception("Bag tag not found");
                }

                // 2. 查询符合条件的包裹
                var cutoffTime = DateTime.UtcNow.AddHours(-84);
                var waybills = await _bagTagRepository.GetEligibleUspsWaybillsAsync(cutoffTime);

                if (waybills.Count == 0)
                {
                    throw new Exception("No eligible waybills found");
                }

                // 3. 创建任务
                var taskId = $"task_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid().ToString("N").Substring(0, 8)}";
                var taskStatus = new AutoPackTaskStatus
                {
                    TaskId = taskId,
                    TagNumber = tagNumber,
                    Status = "processing",
                    TotalCount = waybills.Count,
                    ProcessedCount = 0,
                    SuccessCount = 0,
                    FailedCount = 0,
                    Message = "自动集包任务已启动",
                    StartTime = DateTime.UtcNow,
                    FailedItems = new List<AutoPackFailedItem>(),
                    CancellationTokenSource = new CancellationTokenSource()
                };

                // 4. 保存任务状态到缓存
                await _cacheService.SetAsync($"autopack:{taskId}", taskStatus, 60); // 缓存60分钟

                // 5. 启动后台任务
                _ = Task.Run(async () => await ExecuteAutoPackAsync(taskId, tagNumber, waybills, creator));

                // 6. 返回响应
                return new StartAutoPackResponse
                {
                    TaskId = taskId,
                    TagNumber = tagNumber,
                    Status = "processing",
                    TotalCount = waybills.Count,
                    Message = "自动集包任务已启动"
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in StartAutoPackAsync");
                throw;
            }
        }

        private async Task ExecuteAutoPackAsync(string taskId, string tagNumber, List<string> waybills, string creator)
        {
            var random = new Random();
            var cacheKey = $"autopack:{taskId}";
            bool bagTagOpened = false;

            try
            {
                // 1. 检查并打开袋牌（模拟人工操作）
                var taskStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);
                if (taskStatus != null)
                {
                    var tag = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
                    if (tag != null && tag.Status != "Opened")
                    {
                        // 打开袋牌
                        taskStatus.Message = "正在打开袋牌...";
                        await _cacheService.SetAsync(cacheKey, taskStatus, 60);
                        
                        await OpenBagTagAsync(tagNumber);
                        
                        // 更新袋牌备注为 USPS 自动集包袋牌
                        var tagToUpdate = await _bagTagRepository.GetByTagNumberAsync(tagNumber);
                        if (tagToUpdate != null && string.IsNullOrEmpty(tagToUpdate.Remark))
                        {
                            tagToUpdate.Remark = "USPS自动集包袋牌";
                            await _bagTagRepository.UpdateAsync(tagToUpdate);
                        }
                        
                        bagTagOpened = true;
                        
                        // 延迟 1-2 秒，模拟人工操作
                        await Task.Delay(random.Next(1000, 2001));
                    }
                    else if (tag != null && string.IsNullOrEmpty(tag.Remark))
                    {
                        // 如果袋牌已打开但没有备注，添加备注
                        tag.Remark = "USPS自动集包袋牌";
                        await _bagTagRepository.UpdateAsync(tag);
                    }
                }

                // 2. 执行集包操作
                foreach (var waybill in waybills)
                {
                    // 获取任务状态
                    taskStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);
                    if (taskStatus == null || taskStatus.CancellationTokenSource?.IsCancellationRequested == true)
                    {
                        break;
                    }

                    // 更新当前处理单号
                    taskStatus.CurrentWaybill = waybill;
                    await _cacheService.SetAsync(cacheKey, taskStatus, 60);

                    try
                    {
                        // 执行关联
                        var (success, errorCode, errorMessage) = await AssociateWaybillAsync(tagNumber, waybill, creator);

                        if (success)
                        {
                            taskStatus.SuccessCount++;
                        }
                        else
                        {
                            taskStatus.FailedCount++;
                            taskStatus.FailedItems.Add(new AutoPackFailedItem
                            {
                                WaybillNumber = waybill,
                                ErrorCode = errorCode,
                                ErrorMessage = errorMessage
                            });
                        }
                    }
                    catch (Exception ex)
                    {
                        taskStatus.FailedCount++;
                        taskStatus.FailedItems.Add(new AutoPackFailedItem
                        {
                            WaybillNumber = waybill,
                            ErrorCode = 9999,
                            ErrorMessage = ex.Message
                        });
                    }

                    // 更新进度
                    taskStatus.ProcessedCount++;
                    await _cacheService.SetAsync(cacheKey, taskStatus, 60);

                    // 随机延迟 2-4 秒
                    if (taskStatus.ProcessedCount < waybills.Count)
                    {
                        var delay = random.Next(2000, 4001);
                        await Task.Delay(delay);
                    }
                }

                // 3. 关闭袋牌（模拟人工操作）
                taskStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);
                if (taskStatus != null && !taskStatus.CancellationTokenSource?.IsCancellationRequested == true)
                {
                    taskStatus.Message = "正在关闭袋牌...";
                    await _cacheService.SetAsync(cacheKey, taskStatus, 60);
                    
                    await CloseBagTagAsync(tagNumber);
                    
                    // 延迟 1-2 秒，模拟人工操作
                    await Task.Delay(random.Next(1000, 2001));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in ExecuteAutoPackAsync");
                // 继续执行，确保任务状态更新
            }
            finally
            {
                // 4. 任务完成
                var finalStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);
                if (finalStatus != null)
                {
                    finalStatus.Status = finalStatus.CancellationTokenSource?.IsCancellationRequested == true ? "cancelled" : "completed";
                    finalStatus.EndTime = DateTime.UtcNow;
                    finalStatus.CurrentWaybill = null;
                    finalStatus.Message = bagTagOpened ? "袋牌已自动打开并关闭" : "袋牌操作完成";
                    await _cacheService.SetAsync(cacheKey, finalStatus, 60);
                }
            }
        }

        public async Task<AutoPackProgressResponse> GetAutoPackProgressAsync(string taskId)
        {
            try
            {
                var cacheKey = $"autopack:{taskId}";
                var taskStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);

                if (taskStatus == null)
                {
                    return null;
                }

                // 计算进度百分比
                var progress = taskStatus.TotalCount > 0
                    ? (int)((double)taskStatus.ProcessedCount / taskStatus.TotalCount * 100)
                    : 0;

                // 计算预计完成时间
                DateTime? estimatedEndTime = null;
                if (taskStatus.ProcessedCount > 0 && taskStatus.Status == "processing")
                {
                    var elapsed = DateTime.UtcNow - taskStatus.StartTime;
                    var avgTimePerItem = elapsed.TotalSeconds / taskStatus.ProcessedCount;
                    var remainingItems = taskStatus.TotalCount - taskStatus.ProcessedCount;
                    estimatedEndTime = DateTime.UtcNow.AddSeconds(avgTimePerItem * remainingItems);
                }

                return new AutoPackProgressResponse
                {
                    TaskId = taskStatus.TaskId,
                    TagNumber = taskStatus.TagNumber,
                    Status = taskStatus.Status,
                    TotalCount = taskStatus.TotalCount,
                    ProcessedCount = taskStatus.ProcessedCount,
                    SuccessCount = taskStatus.SuccessCount,
                    FailedCount = taskStatus.FailedCount,
                    CurrentWaybill = taskStatus.CurrentWaybill,
                    Progress = progress,
                    Message = $"正在处理第 {taskStatus.ProcessedCount}/{taskStatus.TotalCount} 个包裹",
                    StartTime = taskStatus.StartTime,
                    EstimatedEndTime = estimatedEndTime,
                    FailedItems = taskStatus.FailedItems
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in GetAutoPackProgressAsync");
                throw;
            }
        }

        public async Task<bool> CancelAutoPackAsync(string taskId)
        {
            try
            {
                var cacheKey = $"autopack:{taskId}";
                var taskStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);

                if (taskStatus == null || taskStatus.Status != "processing")
                {
                    return false;
                }

                taskStatus.CancellationTokenSource?.Cancel();
                taskStatus.Status = "cancelled";
                taskStatus.EndTime = DateTime.UtcNow;
                await _cacheService.SetAsync(cacheKey, taskStatus, 60);

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in CancelAutoPackAsync");
                throw;
            }
        }

        public async Task<AutoPackResultResponse> GetAutoPackResultAsync(string taskId)
        {
            try
            {
                var cacheKey = $"autopack:{taskId}";
                var taskStatus = await _cacheService.GetAsync<AutoPackTaskStatus>(cacheKey);

                if (taskStatus == null)
                {
                    return null;
                }

                var duration = taskStatus.EndTime.HasValue
                    ? (int)(taskStatus.EndTime.Value - taskStatus.StartTime).TotalSeconds
                    : (int)(DateTime.UtcNow - taskStatus.StartTime).TotalSeconds;

                return new AutoPackResultResponse
                {
                    TaskId = taskStatus.TaskId,
                    TagNumber = taskStatus.TagNumber,
                    Status = taskStatus.Status,
                    TotalCount = taskStatus.TotalCount,
                    SuccessCount = taskStatus.SuccessCount,
                    FailedCount = taskStatus.FailedCount,
                    StartTime = taskStatus.StartTime,
                    EndTime = taskStatus.EndTime,
                    Duration = duration,
                    FailedItems = taskStatus.FailedItems
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in GetAutoPackResultAsync");
                throw;
            }
        }
    }
}