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

namespace BLL.Services
{
    /// <summary>
    /// 标签扫描服务实现类
    /// </summary>
    public class LabelScanService : ILabelScanService
    {
        private readonly ILabelScanRepository _labelScanRepository;
        private readonly IOrderLogService _orderLogService;
        private readonly ILogger<LabelScanService> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="labelScanRepository">标签扫描记录仓储</param>
        /// <param name="orderLogService">订单日志服务</param>
        /// <param name="logger">日志记录器</param>
        public LabelScanService(ILabelScanRepository labelScanRepository, IOrderLogService orderLogService, ILogger<LabelScanService> logger)
        {
            _labelScanRepository = labelScanRepository;
            _orderLogService = orderLogService;
            _logger = logger;
        }

        /// <summary>
        /// 记录标签扫描
        /// </summary>
        /// <param name="customerId">客户ID</param>
        /// <param name="neutralWaybillNumber">中性面单单号</param>
        /// <param name="result">扫描结果</param>
        /// <param name="createdBy">创建人</param>
        /// <param name="referenceNumber">参考号</param>
        /// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
        /// <param name="description">描述</param>
        /// <returns>创建的标签扫描记录</returns>
        public async Task<LabelScanEntity> RecordScanAsync(int customerId, string neutralWaybillNumber, ScanResult result, string createdBy,
            string? referenceNumber = null, string? finalMileTrackingNumber = null, string? description = null,
            string? deviceCode = null, string? deviceName = null)
        {
            try
            {
                if (string.IsNullOrEmpty(neutralWaybillNumber))
                {
                    throw new ArgumentException("Neutral waybill number is required");
                }

                if (string.IsNullOrEmpty(createdBy))
                {
                    throw new ArgumentException("Created by is required");
                }

                _logger.LogInformation("Recording scan for neutral waybill number: {number}, CustomerId: {customerId}, Result: {result}", 
                    neutralWaybillNumber, customerId, result);

                // 创建新的扫描记录
                var scanRecord = new LabelScanEntity
                {
                    CustomerId = customerId,
                    NeutralWaybillNumber = neutralWaybillNumber,
                    ReferenceNumber = referenceNumber,
                    FinalMileTrackingNumber = finalMileTrackingNumber,
                    Result = result,
                    Description = description,
                    CreatedBy = createdBy,
                    DeviceCode = deviceCode,
                    DeviceName = deviceName
                };

                await _labelScanRepository.CreateAsync(scanRecord);

                _logger.LogInformation("Scan recorded successfully. NeutralWaybillNumber: {number}, CustomerId: {customerId}, ScanId: {scanId}", 
                    neutralWaybillNumber, customerId, scanRecord.Id);
                
                // 记录订单日志
                await _orderLogService.RecordOrderLogAsync(
                    neutralWaybillNumber: neutralWaybillNumber,
                    finalMileTrackingNumber: finalMileTrackingNumber,
                    operationType: OrderLogOperationType.REPLACE,
                    operationResult: OrderLogOperationResult.SUCCESS,
                    operationDescription: $"换单扫描成功，扫描结果: {result}",
                    @operator: createdBy
                );

                return scanRecord;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error recording scan for neutral waybill number: {number}, CustomerId: {customerId}", 
                    neutralWaybillNumber, customerId);
                
                // 记录订单日志
                await _orderLogService.RecordOrderLogAsync(
                    neutralWaybillNumber: neutralWaybillNumber,
                    finalMileTrackingNumber: finalMileTrackingNumber,
                    operationType: OrderLogOperationType.REPLACE,
                    operationResult: OrderLogOperationResult.FAILED,
                    operationDescription: $"换单扫描失败: {ex.Message}",
                    @operator: createdBy
                );
                
                throw;
            }
        }

        /// <summary>
        /// 根据中性面单单号获取扫描记录列表
        /// </summary>
        /// <param name="neutralWaybillNumber">中性面单单号</param>
        /// <returns>标签扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetScanRecordsByNeutralWaybillNumberAsync(string neutralWaybillNumber)
        {
            try
            {
                if (string.IsNullOrEmpty(neutralWaybillNumber))
                {
                    throw new ArgumentException("Neutral waybill number is required");
                }

                _logger.LogInformation("Getting scan records for neutral waybill number: {number}", neutralWaybillNumber);
                return await _labelScanRepository.GetByNeutralWaybillNumberAsync(neutralWaybillNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan records for neutral waybill number: {number}", neutralWaybillNumber);
                throw;
            }
        }

        /// <summary>
        /// 根据多个中性面单单号获取扫描记录列表
        /// </summary>
        /// <param name="neutralWaybillNumbers">中性面单单号列表</param>
        /// <returns>标签扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetScanRecordsByNeutralWaybillNumbersAsync(List<string> neutralWaybillNumbers)
        {
            try
            {
                if (neutralWaybillNumbers == null || neutralWaybillNumbers.Count == 0)
                {
                    return new List<LabelScanEntity>();
                }

                _logger.LogInformation("Getting scan records for {count} neutral waybill numbers", neutralWaybillNumbers.Count);
                return await _labelScanRepository.GetByNeutralWaybillNumbersAsync(neutralWaybillNumbers);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan records for multiple neutral waybill numbers");
                return new List<LabelScanEntity>();
            }
        }

        /// <summary>
        /// 根据参考号获取扫描记录列表
        /// </summary>
        /// <param name="referenceNumber">参考号</param>
        /// <returns>标签扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetScanRecordsByReferenceNumberAsync(string referenceNumber)
        {
            try
            {
                if (string.IsNullOrEmpty(referenceNumber))
                {
                    throw new ArgumentException("Reference number is required");
                }

                _logger.LogInformation("Getting scan records for reference number: {number}", referenceNumber);
                return await _labelScanRepository.GetByReferenceNumberAsync(referenceNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan records for reference number: {number}", referenceNumber);
                throw;
            }
        }

        /// <summary>
        /// 根据尾程跟踪单号获取扫描记录列表
        /// </summary>
        /// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
        /// <returns>标签扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetScanRecordsByFinalMileTrackingNumberAsync(string finalMileTrackingNumber)
        {
            try
            {
                if (string.IsNullOrEmpty(finalMileTrackingNumber))
                {
                    throw new ArgumentException("Final mile tracking number is required");
                }

                _logger.LogInformation("Getting scan records for final mile tracking number: {number}", finalMileTrackingNumber);
                return await _labelScanRepository.GetByFinalMileTrackingNumberAsync(finalMileTrackingNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan records for final mile tracking number: {number}", finalMileTrackingNumber);
                throw;
            }
        }

        /// <summary>
        /// 根据客户ID获取扫描记录列表
        /// </summary>
        /// <param name="customerId">客户ID</param>
        /// <returns>标签扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetScanRecordsByCustomerIdAsync(int customerId)
        {
            try
            {
                _logger.LogInformation("Getting scan records for customer ID: {customerId}", customerId);
                return await _labelScanRepository.GetByCustomerIdAsync(customerId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan records for customer ID: {customerId}", customerId);
                throw;
            }
        }

        /// <summary>
        /// 根据客户ID和中性面单单号获取扫描记录列表
        /// </summary>
        /// <param name="customerId">客户ID</param>
        /// <param name="neutralWaybillNumber">中性面单单号</param>
        /// <returns>标签扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetScanRecordsByCustomerIdAndWaybillNumberAsync(int customerId, string neutralWaybillNumber)
        {
            try
            {
                if (string.IsNullOrEmpty(neutralWaybillNumber))
                {
                    throw new ArgumentException("Neutral waybill number is required");
                }

                _logger.LogInformation("Getting scan records for customer ID: {customerId}, neutral waybill number: {number}", 
                    customerId, neutralWaybillNumber);
                return await _labelScanRepository.GetByCustomerIdAndWaybillNumberAsync(customerId, neutralWaybillNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan records for customer ID: {customerId}, neutral waybill number: {number}", 
                    customerId, neutralWaybillNumber);
                throw;
            }
        }

        /// <summary>
        /// 统计客户的订单扫描次数
        /// </summary>
        /// <param name="customerId">客户ID</param>
        /// <param name="neutralWaybillNumber">中性面单单号（可选，不提供则统计所有订单）</param>
        /// <returns>扫描次数</returns>
        public async Task<int> CountScansByCustomerAndWaybillAsync(int customerId, string? neutralWaybillNumber = null)
        {
            try
            {
                _logger.LogInformation("Counting scans for customer ID: {customerId}, neutral waybill number: {number}", 
                    customerId, neutralWaybillNumber);
                return await _labelScanRepository.CountScansByCustomerAndWaybillAsync(customerId, neutralWaybillNumber);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error counting scans for customer ID: {customerId}, neutral waybill number: {number}", 
                    customerId, neutralWaybillNumber);
                throw;
            }
        }

        /// <summary>
        /// 获取客户的扫描记录分组统计
        /// </summary>
        /// <param name="customerId">客户ID</param>
        /// <returns>按订单分组的扫描统计信息</returns>
        public async Task<Dictionary<string, int>> GetScanStatsByCustomerAsync(int customerId)
        {
            try
            {
                _logger.LogInformation("Getting scan statistics for customer ID: {customerId}", customerId);
                return await _labelScanRepository.GetScanStatsByCustomerAsync(customerId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting scan statistics for customer ID: {customerId}", customerId);
                throw;
            }
        }

        /// <summary>
        /// 获取所有标签扫描记录
        /// </summary>
        /// <returns>标签扫描记录实体列表</returns>
        public async Task<List<LabelScanEntity>> GetAllLabelScanRecordsAsync()
        {
            try
            {
                _logger.LogInformation("Retrieving all label scan records");
                var records = await _labelScanRepository.GetAllAsync();
                _logger.LogInformation("Found {count} label scan records", records.Count);
                return records;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error retrieving all label scan records");
                return new List<LabelScanEntity>();
            }
        }

        /// <summary>
        /// 分页获取标签扫描记录
        /// </summary>
        /// <param name="page">页码</param>
        /// <param name="pageSize">每页大小</param>
        /// <param name="sortBy">排序字段</param>
        /// <param name="sortOrder">排序顺序</param>
        /// <param name="customerId">客户ID</param>
        /// <param name="referenceNumber">参考号</param>
        /// <param name="neutralWaybillNumber">中性面单单号</param>
        /// <param name="finalMileTrackingNumber">尾程跟踪单号</param>
        /// <param name="result">扫描结果</param>
        /// <returns>标签扫描记录DTO列表和总记录数</returns>
        public async Task<(List<MDL.DTOs.LabelScanWithCustomerDto>, int)> GetLabelScanRecordsByPageAsync(int page, int pageSize, string sortBy, string sortOrder, int? customerId, string referenceNumber, string neutralWaybillNumber, string finalMileTrackingNumber, int? result, string startCreatedAt, string endCreatedAt)
        {
            try
            {
                _logger.LogInformation("Retrieving label scan records by page. Page: {page}, PageSize: {pageSize}, SortBy: {sortBy}, SortOrder: {sortOrder}", page, pageSize, sortBy, sortOrder);
                var (records, totalCount) = await _labelScanRepository.GetByPageAsync(page, pageSize, sortBy, sortOrder, customerId, referenceNumber, neutralWaybillNumber, finalMileTrackingNumber, result, startCreatedAt, endCreatedAt);
                _logger.LogInformation("Found {count} label scan records, total: {total}", records.Count, totalCount);
                return (records, totalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error retrieving label scan records by page");
                return (new List<MDL.DTOs.LabelScanWithCustomerDto>(), 0);
            }
        }

        /// <summary>
        /// 获取当天扫描后未下单数量
        /// </summary>
        /// <returns>当天未下单数据</returns>
        public async Task<MDL.DTOs.TodayUnorderedDataDto> GetTodayUnorderedCountAsync()
        {
            try
            {
                _logger.LogInformation("Retrieving today's unordered count");

                // 获取当天的日期范围
                var today = DateTime.Today;
                var startOfDay = today.Date;
                var endOfDay = today.Date.AddDays(1).AddTicks(-1);

                // 获取当天所有扫描记录
                var allScans = await _labelScanRepository.GetByDateRangeAsync(startOfDay, endOfDay);

                // 计算扫描总数
                int totalCount = allScans.Count;

                // 计算未下单数量（结果为未下单的扫描记录）
                int unorderedCount = allScans.Count(scan => scan.Result == ScanResult.NoOrderData);

                // 计算未下单率
                string unorderedRate = "0%";
                if (totalCount > 0)
                {
                    double rate = (double)unorderedCount / totalCount * 100;
                    unorderedRate = $"{rate:F2}%";
                }

                // 创建返回数据
                var result = new MDL.DTOs.TodayUnorderedDataDto
                {
                    UnorderedCount = unorderedCount,
                    TotalCount = totalCount,
                    UnorderedRate = unorderedRate,
                    Date = today.ToString("yyyy-MM-dd")
                };

                _logger.LogInformation("Today's unordered count: {unordered}, total: {total}, rate: {rate}", unorderedCount, totalCount, unorderedRate);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error retrieving today's unordered count");
                // 返回默认值
                return new MDL.DTOs.TodayUnorderedDataDto
                {
                    UnorderedCount = 0,
                    TotalCount = 0,
                    UnorderedRate = "0%",
                    Date = DateTime.Today.ToString("yyyy-MM-dd")
                };
            }
        }

        /// <summary>
        /// 获取指定条件的最新扫描记录（按订单号分组，取最新的一条）
        /// </summary>
        /// <param name="waybillNumbers">中性面单单号列表（可选）</param>
        /// <param name="startTime">开始时间（可选）</param>
        /// <param name="endTime">结束时间（可选）</param>
        /// <param name="customerId">客户ID（可选）</param>
        /// <returns>最新扫描记录列表</returns>
        public async Task<List<LabelScanEntity>> GetLatestScanRecordsAsync(
            List<string> waybillNumbers = null,
            DateTime? startTime = null,
            DateTime? endTime = null,
            int? customerId = null)
        {
            try
            {
                _logger.LogInformation("Getting latest scan records. WaybillCount: {count}, StartTime: {start}, EndTime: {end}, CustomerId: {customerId}",
                    waybillNumbers?.Count ?? 0, startTime, endTime, customerId);

                var records = await _labelScanRepository.GetLatestScanRecordsAsync(waybillNumbers, startTime, endTime, customerId);
                _logger.LogInformation("Found {count} latest scan records", records.Count);
                return records;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting latest scan records");
                return new List<LabelScanEntity>();
            }
        }
    }
}