using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BLL.Interfaces;
using DAL.Interfaces;
using MDL.DTOs;
using MDL.Models;
using Microsoft.Extensions.Logging;
using DB.Database;

namespace BLL.Services
{
    /// <summary>
    /// 指标计算服务实现
    /// </summary>
    public class MetricsCalculationService : IMetricsCalculationService
    {
        private const int UTC_5_OFFSET = -5;
        
        private readonly ILabelReplaceRepository _labelReplaceRepository;
        private readonly ILabelScanRepository _labelScanRepository;
        private readonly IArrivalHandoverFormRepository _arrivalHandoverFormRepository;
        private readonly ISqlSugarProvider _provider;
        private readonly ILogger<MetricsCalculationService> _logger;

        public MetricsCalculationService(
            ILabelReplaceRepository labelReplaceRepository,
            ILabelScanRepository labelScanRepository,
            IArrivalHandoverFormRepository arrivalHandoverFormRepository,
            ISqlSugarProvider provider,
            ILogger<MetricsCalculationService> logger)
        {
            _labelReplaceRepository = labelReplaceRepository;
            _labelScanRepository = labelScanRepository;
            _arrivalHandoverFormRepository = arrivalHandoverFormRepository;
            _provider = provider;
            _logger = logger;
        }

        #region 时间转换方法

        public DateTime ConvertUtcToUtc5(DateTime utcTime)
        {
            return utcTime.AddHours(UTC_5_OFFSET);
        }

        public DateTime ConvertUtc5ToUtc(DateTime utc5Time)
        {
            return utc5Time.AddHours(-UTC_5_OFFSET);
        }

        public DateTime GetUtc5Today()
        {
            var now = DateTime.UtcNow;
            var utc5Now = ConvertUtcToUtc5(now);
            return utc5Now.Date;
        }

        public DateTime GetUtc5DateStart(DateTime utc5Date)
        {
            var utc5Start = utc5Date.Date;
            return ConvertUtc5ToUtc(utc5Start);
        }

        public DateTime GetUtc5DateEnd(DateTime utc5Date)
        {
            var utc5End = utc5Date.Date.AddDays(1).AddSeconds(-1);
            return ConvertUtc5ToUtc(utc5End);
        }

        #endregion

        #region 标签率计算

        /// <summary>
        /// 计算交接单的标签率
        /// </summary>
        private async Task<double> CalculateLabelRateAtFirstScanAsync(string handoverNumber)
        {
            _logger.LogInformation("Calculating label rate for handover: {handoverNumber}", handoverNumber);
            
            var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(handoverNumber);
            
            if (orders.Count == 0)
            {
                _logger.LogWarning("No orders found for handover number: {handoverNumber}", handoverNumber);
                return 0;
            }

            var waybills = orders.Select(o => o.NeutralWaybillNumber).ToList();
            var allScans = await _labelScanRepository.GetByNeutralWaybillNumbersAsync(waybills);

            // 情况1：交接单不存在任何扫描记录
            if (allScans == null || allScans.Count == 0)
            {
                int labeledCount = orders.Count(o => !string.IsNullOrEmpty(o.Label));
                double rate = (double)labeledCount / orders.Count;
                _logger.LogInformation("No scan records for handover {handoverNumber}, label rate: {rate}", handoverNumber, rate);
                return rate;
            }

            // 情况2：交接单存在扫描记录，找到最早的扫描时间
            var earliestScanTime = allScans.Min(s => s.CreatedAt);
            _logger.LogInformation("First scan time for handover {handoverNumber}: {scanTime}", handoverNumber, earliestScanTime);

            int labeledAtScanTime = 0;
            foreach (var order in orders)
            {
                if (!string.IsNullOrEmpty(order.Label))
                {
                    var labelRetrievedAt = order.LabelRetrievedAt ?? order.CreatedAt;
                    if (labelRetrievedAt <= earliestScanTime)
                    {
                        labeledAtScanTime++;
                    }
                }
            }

            double labelRate = (double)labeledAtScanTime / orders.Count;
            _logger.LogInformation("Label rate for handover {handoverNumber} at first scan: {rate}", handoverNumber, labelRate);
            return labelRate;
        }

        public async Task<LabelRateMetricsDto> GetLabelRateAsync(string handoverNumber)
        {
            var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(handoverNumber);
            var labelRate = await CalculateLabelRateAtFirstScanAsync(handoverNumber);
            var labeledCount = orders.Count(o => !string.IsNullOrEmpty(o.Label));

            var waybills = orders.Select(o => o.NeutralWaybillNumber).ToList();
            var scans = await _labelScanRepository.GetByNeutralWaybillNumbersAsync(waybills);
            var firstScanTime = scans?.Count > 0 ? scans.Min(s => s.CreatedAt) : (DateTime?)null;

            return new LabelRateMetricsDto
            {
                HandoverNumber = handoverNumber,
                TotalOrderCount = orders.Count,
                LabeledOrderCount = labeledCount,
                LabelRate = labelRate,
                FirstScanTime = firstScanTime
            };
        }

        #endregion

        #region 当日统计指标

        public async Task<int> GetDailyNewReplaceCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var arrivalForms = await _arrivalHandoverFormRepository.GetArrivalHandoverFormsByDateRangeAsync(dateStart, dateEnd);

            if (arrivalForms.Count == 0)
                return 0;

            var handoverNumbers = arrivalForms.Select(f => f.HandoverNumber).ToList();
            var orders = await _labelReplaceRepository.GetOrdersByHandoverNumbersAsync(handoverNumbers);

            int count = orders.Count(o => !string.IsNullOrEmpty(o.Label));
            _logger.LogInformation("Daily new replace count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetCumulativeTotalReplaceCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);

            var labeledOrders = await _labelReplaceRepository.GetAllOrdersWithLabelsAsync();
            var pastOrders = labeledOrders.Where(o => (o.LabelRetrievedAt ?? o.CreatedAt) < dateStart).ToList();

            if (pastOrders.Count == 0)
                return 0;

            var waybills = pastOrders.Select(o => o.NeutralWaybillNumber).ToList();
            var scans = await _labelScanRepository.GetByNeutralWaybillNumbersAsync(waybills);

            var successfulWaybills = scans
                .Where(s => s.Result == ScanResult.ReturnedLabel)
                .Select(s => s.NeutralWaybillNumber)
                .ToHashSet();

            int count = pastOrders.Count(o => !successfulWaybills.Contains(o.NeutralWaybillNumber));
            _logger.LogInformation("Cumulative total replace count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetDailyCompletionCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var successfulScans = await _labelScanRepository.GetScanRecordsByDateRangeAsync(dateStart, dateEnd, ScanResult.ReturnedLabel);

            if (successfulScans == null || successfulScans.Count == 0)
                return 0;

            var uniqueWaybills = successfulScans
                .Select(s => s.NeutralWaybillNumber)
                .Distinct()
                .Count();

            _logger.LogInformation("Daily completion count for {date}: {count}", date, uniqueWaybills);
            return uniqueWaybills;
        }

        public async Task<int> GetDailyStopCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var successfulScans = await _labelScanRepository.GetScanRecordsByDateRangeAsync(dateStart, dateEnd, ScanResult.ReturnedLabel);

            if (successfulScans == null || successfulScans.Count == 0)
                return 0;

            var stopCount = successfulScans
                .Where(s => s.Description != null && s.Description.Contains("STOP", StringComparison.OrdinalIgnoreCase))
                .Select(s => s.NeutralWaybillNumber)
                .Distinct()
                .Count();

            _logger.LogInformation("Daily STOP count for {date}: {count}", date, stopCount);
            return stopCount;
        }

        public async Task<int> GetDailyLabelPushCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var allOrders = await _labelReplaceRepository.GetAllOrdersWithLabelsAsync();

            int count = allOrders.Count(o =>
                o.LabelRetrievedAt.HasValue &&
                o.LabelRetrievedAt >= dateStart &&
                o.LabelRetrievedAt <= dateEnd
            );

            _logger.LogInformation("Daily label push count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetDailyUnfinishedFailureCountAsync()
        {
            return await GetCumulativeTotalReplaceCountAsync(GetUtc5Today());
        }

        public async Task<int> GetDailyFailureCountAsync(DateTime date)
        {
            var shouldReplaceCount = await GetDailyShouldReplaceCountAsync(date);
            var completionCount = await GetDailyCompletionCountAsync(date);
            int failureCount = Math.Max(0, shouldReplaceCount - completionCount);
            _logger.LogInformation("Daily failure count for {date}: {count}", date, failureCount);
            return failureCount;
        }

        public async Task<int> GetDailySuccessCountAsync(DateTime date)
        {
            return await GetDailyCompletionCountAsync(date);
        }

        public async Task<int> GetDailyShouldReplaceCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var arrivalForms = await _arrivalHandoverFormRepository.GetArrivalHandoverFormsByDateRangeAsync(dateStart, dateEnd);

            if (arrivalForms.Count == 0)
                return 0;

            int totalCount = 0;
            foreach (var form in arrivalForms)
            {
                var labelRate = await CalculateLabelRateAtFirstScanAsync(form.HandoverNumber);

                if (labelRate >= 0.80)
                {
                    var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(form.HandoverNumber);
                    totalCount += orders.Count;
                }
            }

            _logger.LogInformation("Daily should replace count for {date}: {count}", date, totalCount);
            return totalCount;
        }

        public async Task<int> GetBeforeNoonArrivedCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var arrivalForms = await _arrivalHandoverFormRepository.GetArrivalHandoverFormsByDateRangeAsync(dateStart, dateEnd);
            
            var count = 0;
            foreach (var form in arrivalForms)
            {
                if (form.ReceiptTime.HasValue)
                {
                    var receiptUtc5 = ConvertUtcToUtc5(form.ReceiptTime.Value);
                    var timeOfDay = receiptUtc5.TimeOfDay;
                    if (timeOfDay <= TimeSpan.FromHours(16))
                    {
                        var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(form.HandoverNumber);
                        count += orders.Count;
                    }
                }
            }

            _logger.LogInformation("Before noon arrived count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetAfternoonArrivedCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var arrivalForms = await _arrivalHandoverFormRepository.GetArrivalHandoverFormsByDateRangeAsync(dateStart, dateEnd);

            var count = 0;
            foreach (var form in arrivalForms)
            {
                if (form.ReceiptTime.HasValue)
                {
                    var receiptUtc5 = ConvertUtcToUtc5(form.ReceiptTime.Value);
                    var timeOfDay = receiptUtc5.TimeOfDay;
                    if (timeOfDay > TimeSpan.FromHours(16))
                    {
                        var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(form.HandoverNumber);
                        count += orders.Count;
                    }
                }
            }

            _logger.LogInformation("Afternoon arrived count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetBeforeNoonPassedCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var arrivalForms = await _arrivalHandoverFormRepository.GetArrivalHandoverFormsByDateRangeAsync(dateStart, dateEnd);

            var count = 0;
            foreach (var form in arrivalForms)
            {
                if (form.ReceiptTime.HasValue)
                {
                    var receiptUtc5 = ConvertUtcToUtc5(form.ReceiptTime.Value);
                    var timeOfDay = receiptUtc5.TimeOfDay;
                    
                    if (timeOfDay <= TimeSpan.FromHours(16))
                    {
                        var labelRate = await CalculateLabelRateAtFirstScanAsync(form.HandoverNumber);
                        if (labelRate >= 0.80)
                        {
                            var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(form.HandoverNumber);
                            var waybills = orders.Select(o => o.NeutralWaybillNumber).ToList();

                            var assessmentTime = form.ReceiptTime.Value.Date.AddDays(1).AddHours(16);

                            foreach (var waybill in waybills)
                            {
                                var hasSuccessScan = await _labelScanRepository.HasSuccessScanBeforeAsync(waybill, assessmentTime);
                                if (hasSuccessScan)
                                {
                                    count++;
                                }
                            }
                        }
                    }
                }
            }

            _logger.LogInformation("Before noon passed count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetAfternoonPassedCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var arrivalForms = await _arrivalHandoverFormRepository.GetArrivalHandoverFormsByDateRangeAsync(dateStart, dateEnd);

            var count = 0;
            foreach (var form in arrivalForms)
            {
                if (form.ReceiptTime.HasValue)
                {
                    var receiptUtc5 = ConvertUtcToUtc5(form.ReceiptTime.Value);
                    var timeOfDay = receiptUtc5.TimeOfDay;

                    if (timeOfDay > TimeSpan.FromHours(16))
                    {
                        var labelRate = await CalculateLabelRateAtFirstScanAsync(form.HandoverNumber);
                        if (labelRate >= 0.80)
                        {
                            var orders = await _labelReplaceRepository.GetOrdersByHandoverNumberAsync(form.HandoverNumber);
                            var waybills = orders.Select(o => o.NeutralWaybillNumber).ToList();

                            var assessmentTime = form.ReceiptTime.Value.Date.AddDays(1).AddHours(23).AddMinutes(59);

                            foreach (var waybill in waybills)
                            {
                                var hasSuccessScan = await _labelScanRepository.HasSuccessScanBeforeAsync(waybill, assessmentTime);
                                if (hasSuccessScan)
                                {
                                    count++;
                                }
                            }
                        }
                    }
                }
            }

            _logger.LogInformation("Afternoon passed count for {date}: {count}", date, count);
            return count;
        }

        public async Task<int> GetDailyScanCountAsync(DateTime date)
        {
            var dateStart = GetUtc5DateStart(date);
            var dateEnd = GetUtc5DateEnd(date);

            var allScans = await _labelScanRepository.GetScanRecordsByDateRangeAsync(dateStart, dateEnd, resultFilter: null);

            int count = allScans?.Count ?? 0;
            _logger.LogInformation("Daily scan count for {date}: {count}", date, count);
            return count;
        }

        #endregion

        #region 完成率计算

        public async Task<double> Calculate24HCompletionRateAsync(DateTime date)
        {
            var shouldReplaceCount = await GetDailyShouldReplaceCountAsync(date);
            var completionCount = await GetDailyCompletionCountAsync(date);

            double rate = shouldReplaceCount > 0 ? (double)completionCount / shouldReplaceCount * 100 : 0;
            _logger.LogInformation("24H completion rate for {date}: {rate}%", date, rate);
            return rate;
        }

        public async Task<double> CalculateDailyCompletionRateAsync(DateTime date)
        {
            return await Calculate24HCompletionRateAsync(date);
        }

        #endregion

        #region 完整日统计

        public async Task<Daily24HCompletionRateDto> GetDailySummaryAsync(DateTime date)
        {
            _logger.LogInformation("=== GetDailySummaryAsync START ===");
            _logger.LogInformation("查询日期: {date:yyyy-MM-dd}", date);
            _logger.LogInformation("Getting daily summary for {date} from optimized stored procedure", date);

            try
            {
                // 直接调用存储过程，替代 11 个独立的数据库查询
                var db = _provider.GetClient();
                
                // 使用存储过程查询，支持参数化日期查询
                string sql = $"CALL sp_GetDailyMetricsSummary('{date:yyyy-MM-dd}')";
                _logger.LogInformation("执行SQL: {sql}", sql);
                var summaryList = await db.SqlQueryable<dynamic>(sql).ToListAsync();
                
                _logger.LogInformation("存储过程返回行数: {count}", summaryList?.Count ?? 0);
                
                if (summaryList == null || summaryList.Count == 0)
                {
                    _logger.LogWarning("未找到指标数据 {date}, 返回默认值", date);
                    return GetDefaultSummary(date);
                }

                var summary = summaryList[0];
                
                _logger.LogInformation("存储过程返回第一行数据:");
                _logger.LogInformation("  DailyShouldReplaceCount: {count}", (int?)(summary?.DailyShouldReplaceCount) ?? 0);
                _logger.LogInformation("  DailySuccessCount: {count}", (int?)(summary?.DailySuccessCount) ?? 0);
                _logger.LogInformation("  CumulativeTotalReplaceCount: {count}", (int?)(summary?.CumulativeTotalReplaceCount) ?? 0);
                _logger.LogInformation("  DailyNewReplaceCount: {count}", (int?)(summary?.DailyNewReplaceCount) ?? 0);

                // 将动态对象映射到 DTO
                double dailyCompletionRate = (summary.DailyShouldReplaceCount ?? 0) > 0 
                    ? ((double)(summary.DailySuccessCount ?? 0) / (summary.DailyShouldReplaceCount ?? 0) * 100) 
                    : 0;
                
                double rate24Hour = (summary.DailyShouldReplaceCount ?? 0) > 0 
                    ? ((double)(summary.DailySuccessCount ?? 0) / (summary.DailyShouldReplaceCount ?? 0) * 100) 
                    : 0;

                var result = new Daily24HCompletionRateDto
                {
                    Date = date,
                    DailyNewReplaceCount = summary.DailyNewReplaceCount ?? 0,
                    CumulativeTotalReplaceCount = summary.CumulativeTotalReplaceCount ?? 0,
                    UnfinishedFailureCount = summary.CumulativeTotalReplaceCount ?? 0,
                    DailyFailureCount = summary.DailyFailureCount ?? 0,
                    DailySuccessCount = summary.DailySuccessCount ?? 0,
                    DailyStopCount = summary.DailyStopCount ?? 0,
                    DailyShouldReplaceCount = summary.DailyShouldReplaceCount ?? 0,
                    HighLabelRateOrderCount = summary.DailyShouldReplaceCount ?? 0,
                    CompletedOnTimeCount = summary.DailySuccessCount ?? 0,
                    DailyCompletionRate = $"{dailyCompletionRate:F2}%",
                    Rate24Hour = $"{rate24Hour:F2}%",
                    DailyLabelPushCount = summary.DailyLabelPushCount ?? 0,
                    DailyScanCount = summary.DailyScanCount ?? 0,
                    BeforeNoonArrivedCount = summary.BeforeNoonArrivedCount ?? 0,
                    AfternoonArrivedCount = summary.AfternoonArrivedCount ?? 0,
                    BeforeNoonPassedCount = summary.BeforeNoonPassedCount ?? 0,
                    AfternoonPassedCount = summary.AfternoonPassedCount ?? 0,
                    DataFetchTime = ConvertUtcToUtc5(DateTime.UtcNow)
                };
                
                _logger.LogInformation("=== GetDailySummaryAsync SUCCESS ===");

                _logger.LogInformation("Daily summary retrieved from optimized stored procedure for {date}", date);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "=== GetDailySummaryAsync ERROR ===");
                _logger.LogError(ex, "Error getting daily summary from stored procedure for {date}, falling back to calculation", date);
                
                // 降级方案：如果视图查询失败，回到原来的计算方式
                return await GetDailySummaryAsync_Original(date);
            }
        }

        /// <summary>
        /// 原始的日汇总计算方法（作为降级方案保留）
        /// </summary>
        private async Task<Daily24HCompletionRateDto> GetDailySummaryAsync_Original(DateTime date)
        {
            var newReplaceCountTask = GetDailyNewReplaceCountAsync(date);
            var cumulativeCountTask = GetCumulativeTotalReplaceCountAsync(date);
            var completionCountTask = GetDailyCompletionCountAsync(date);
            var stopCountTask = GetDailyStopCountAsync(date);
            var labelPushCountTask = GetDailyLabelPushCountAsync(date);
            var shouldReplaceCountTask = GetDailyShouldReplaceCountAsync(date);
            var scanCountTask = GetDailyScanCountAsync(date);
            var beforeNoonCountTask = GetBeforeNoonArrivedCountAsync(date);
            var afternoonCountTask = GetAfternoonArrivedCountAsync(date);
            var beforeNoonPassedTask = GetBeforeNoonPassedCountAsync(date);
            var afternoonPassedTask = GetAfternoonPassedCountAsync(date);

            await Task.WhenAll(
                newReplaceCountTask, cumulativeCountTask, completionCountTask,
                stopCountTask, labelPushCountTask, shouldReplaceCountTask, scanCountTask,
                beforeNoonCountTask, afternoonCountTask, beforeNoonPassedTask, afternoonPassedTask
            );

            int newReplaceCount = await newReplaceCountTask;
            int cumulativeCount = await cumulativeCountTask;
            int completionCount = await completionCountTask;
            int stopCount = await stopCountTask;
            int labelPushCount = await labelPushCountTask;
            int shouldReplaceCount = await shouldReplaceCountTask;
            int scanCount = await scanCountTask;
            int beforeNoonCount = await beforeNoonCountTask;
            int afternoonCount = await afternoonCountTask;
            int beforeNoonPassed = await beforeNoonPassedTask;
            int afternoonPassed = await afternoonPassedTask;

            double dailyCompletionRate = shouldReplaceCount > 0 ? (double)completionCount / shouldReplaceCount * 100 : 0;
            double rate24Hour = shouldReplaceCount > 0 ? (double)completionCount / shouldReplaceCount * 100 : 0;

            int unfinishedFailureCount = cumulativeCount;
            int dailyFailureCount = Math.Max(0, shouldReplaceCount - completionCount);
            int dailySuccessCount = completionCount;

            var result = new Daily24HCompletionRateDto
            {
                Date = date,
                DailyNewReplaceCount = newReplaceCount,
                CumulativeTotalReplaceCount = cumulativeCount,
                UnfinishedFailureCount = unfinishedFailureCount,
                DailyFailureCount = dailyFailureCount,
                DailySuccessCount = dailySuccessCount,
                DailyStopCount = stopCount,
                DailyShouldReplaceCount = shouldReplaceCount,
                HighLabelRateOrderCount = shouldReplaceCount,
                CompletedOnTimeCount = completionCount,
                DailyCompletionRate = $"{dailyCompletionRate:F2}%",
                Rate24Hour = $"{rate24Hour:F2}%",
                DailyLabelPushCount = labelPushCount,
                DailyScanCount = scanCount,
                BeforeNoonArrivedCount = beforeNoonCount,
                AfternoonArrivedCount = afternoonCount,
                BeforeNoonPassedCount = beforeNoonPassed,
                AfternoonPassedCount = afternoonPassed,
                DataFetchTime = ConvertUtcToUtc5(DateTime.UtcNow)
            };

            _logger.LogInformation("Daily summary computed using fallback method for {date}", date);
            return result;
        }

        /// <summary>
        /// 获取默认的空汇总数据
        /// </summary>
        private Daily24HCompletionRateDto GetDefaultSummary(DateTime date)
        {
            return new Daily24HCompletionRateDto
            {
                Date = date,
                DailyNewReplaceCount = 0,
                CumulativeTotalReplaceCount = 0,
                UnfinishedFailureCount = 0,
                DailyFailureCount = 0,
                DailySuccessCount = 0,
                DailyStopCount = 0,
                DailyShouldReplaceCount = 0,
                HighLabelRateOrderCount = 0,
                CompletedOnTimeCount = 0,
                DailyCompletionRate = "0.00%",
                Rate24Hour = "0.00%",
                DailyLabelPushCount = 0,
                DailyScanCount = 0,
                BeforeNoonArrivedCount = 0,
                AfternoonArrivedCount = 0,
                BeforeNoonPassedCount = 0,
                AfternoonPassedCount = 0,
                DataFetchTime = ConvertUtcToUtc5(DateTime.UtcNow)
            };
        }

        #endregion

        #region 批量计算

        public async Task<List<MetricsCalculationDto>> GetBatchOrderMetricsAsync(List<string> neutralWaybillNumbers)
        {
            var results = new List<MetricsCalculationDto>();

            foreach (var waybill in neutralWaybillNumbers)
            {
                var metrics = await GetOrderMetricsAsync(waybill);
                results.Add(metrics);
            }

            _logger.LogInformation("Batch order metrics computed for {count} orders", results.Count);
            return results;
        }

        public async Task<List<Daily24HCompletionRateDto>> GetDailySummariesAsync(DateTime startDate, DateTime endDate)
        {
            var results = new List<Daily24HCompletionRateDto>();
            var currentDate = startDate.Date;

            while (currentDate <= endDate.Date)
            {
                var summary = await GetDailySummaryAsync(currentDate);
                results.Add(summary);
                currentDate = currentDate.AddDays(1);
            }

            _logger.LogInformation("Daily summaries computed for {count} days", results.Count);
            return results;
        }

        #endregion

        #region 其他方法

        public async Task<MetricsCalculationDto> GetOrderMetricsAsync(string neutralWaybillNumber)
        {
            _logger.LogInformation("Getting metrics for order: {waybillNumber}", neutralWaybillNumber);
            
            var dto = new MetricsCalculationDto { NeutralWaybillNumber = neutralWaybillNumber };
            
            // 获取订单基本信息
            var order = await _labelReplaceRepository.GetByWaybillNumberAsync(neutralWaybillNumber);
            if (order == null)
            {
                _logger.LogWarning("Order not found: {waybillNumber}", neutralWaybillNumber);
                return dto;
            }
            
            // 获取交接单信息（通过 BillOfLadingNumber 或 MasterPackageNumber）
            string handoverNumber = null;
            List<ArrivalHandoverFormEntity> arrivalForms = null;
            
            if (!string.IsNullOrWhiteSpace(order.BillOfLadingNumber))
            {
                // 这里需要实现通过 BillOfLadingNumber 查询交接单
                // 暂时使用交接单列表查询后过滤（需要在 Repository 中实现更优的查询）
            }
            
            if (!string.IsNullOrWhiteSpace(order.MasterPackageNumber))
            {
                // 这里需要实现通过 MasterPackageNumber 查询交接单
            }
            
            // 如果无法找到交接单，返回基本信息
            if (string.IsNullOrWhiteSpace(handoverNumber))
            {
                _logger.LogWarning("No handover form found for order: {waybillNumber}", neutralWaybillNumber);
                dto.ReceiptTime = null;
                return dto;
            }
            
            var arrivalForm = arrivalForms?.FirstOrDefault();
            if (arrivalForm == null)
            {
                _logger.LogWarning("Arrival form not found for order: {waybillNumber}", neutralWaybillNumber);
                return dto;
            }

            dto.HandoverNumber = handoverNumber;
            dto.ReceiptTime = arrivalForm.ReceiptTime;
            dto.ArrivalDate = arrivalForm.ReceiptTime?.Date;

            // 计算该交接单的标签率
            var labelRate = await CalculateLabelRateAtFirstScanAsync(handoverNumber);
            dto.LabelRate = labelRate;
            dto.IsHighLabelRate = labelRate >= 0.80;

            // 获取第一条扫描记录
            var firstScan = await _labelScanRepository.GetFirstScanRecordByWaybillNumberAsync(neutralWaybillNumber);
            if (firstScan != null)
            {
                dto.FirstScanTime = firstScan.CreatedAt;
                dto.FirstScanResult = (int)firstScan.Result;
            }

            // 根据标签率和收货时间计算考核时间
            DateTime assessmentTime;
            if (labelRate >= 0.80)
            {
                // 高标签率情况
                if (arrivalForm.ReceiptTime.HasValue)
                {
                    var receiptUtc5 = ConvertUtcToUtc5(arrivalForm.ReceiptTime.Value);
                    var timeOfDay = receiptUtc5.TimeOfDay;
                    
                    if (timeOfDay <= TimeSpan.FromHours(16))
                    {
                        // 16:00前收货
                        assessmentTime = arrivalForm.ReceiptTime.Value.Date.AddDays(1).AddHours(16);
                    }
                    else
                    {
                        // 16:00后收货
                        assessmentTime = arrivalForm.ReceiptTime.Value.Date.AddDays(1).AddHours(23).AddMinutes(59);
                    }
                }
                else
                {
                    // 无收货时间，不参与考核
                    _logger.LogWarning("No receipt time for order: {waybillNumber}", neutralWaybillNumber);
                    assessmentTime = DateTime.MaxValue;
                }
            }
            else
            {
                // 低标签率情况：以换单完成时间作为考核时间
                var firstSuccessScan = await _labelScanRepository.GetFirstSuccessScanAsync(neutralWaybillNumber);
                if (firstSuccessScan == null)
                {
                    // 未完成
                    _logger.LogInformation("No successful scan for order: {waybillNumber}", neutralWaybillNumber);
                    assessmentTime = DateTime.MaxValue;
                    dto.CompletedOnTime = false;
                }
                else
                {
                    assessmentTime = firstSuccessScan.CreatedAt;
                    dto.CompletionTime = firstSuccessScan.CreatedAt;
                    dto.CompletedOnTime = true;
                }
            }

            dto.AssessmentTime = assessmentTime;
            dto.AssessmentDate = assessmentTime.Date;

            // 检查是否在考核时间内完成
            if (assessmentTime != DateTime.MaxValue)
            {
                var completedOnTime = await _labelScanRepository.HasSuccessScanBeforeAsync(neutralWaybillNumber, assessmentTime);
                dto.CompletedOnTime = completedOnTime;

                if (completedOnTime)
                {
                    var completionScan = await _labelScanRepository.GetFirstSuccessScanAsync(neutralWaybillNumber);
                    dto.CompletionTime = completionScan?.CreatedAt;
                }
            }

            _logger.LogInformation("Order metrics computed for {waybillNumber}: LabelRate={rate}, CompletedOnTime={completed}", 
                neutralWaybillNumber, dto.LabelRate, dto.CompletedOnTime);
            
            return dto;
        }

        public async Task<bool> RecalculateAndCacheLabelRateAsync(string handoverNumber)
        {
            _logger.LogInformation("Recalculating label rate for handover: {handoverNumber}", handoverNumber);
            var result = await CalculateLabelRateAtFirstScanAsync(handoverNumber);
            return result >= 0;
        }

        #endregion
    }
}
