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

namespace BLL.Services
{
    /// <summary>
    /// 出货交接单与袋牌关联服务实现
    /// </summary>
    public class ShippingHandoverFormBagTagService : IShippingHandoverFormBagTagService
    {
        private readonly IShippingHandoverFormBagTagRepository _repository;
        private readonly IBagTagRepository _bagTagRepository;
        private readonly ILogger<ShippingHandoverFormBagTagService> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="repository">关联仓库</param>
        /// <param name="bagTagRepository">袋牌仓库</param>
        /// <param name="logger">日志记录器</param>
        public ShippingHandoverFormBagTagService(
            IShippingHandoverFormBagTagRepository repository,
            IBagTagRepository bagTagRepository,
            ILogger<ShippingHandoverFormBagTagService> logger)
        {
            _repository = repository;
            _bagTagRepository = bagTagRepository;
            _logger = logger;
        }

        /// <summary>
        /// 关联袋牌到出货交接单
        /// </summary>
        /// <param name="shippingHandoverFormId">出货交接单ID</param>
        /// <param name="bagTagIds">袋牌ID列表</param>
        /// <returns>影响行数</returns>
        public async Task<int> AssociateBagTagsAsync(int shippingHandoverFormId, List<int> bagTagIds)
        {
            _logger.LogInformation("Associating bag tags to shipping handover form: {ShippingHandoverFormId}, BagTagIds: {BagTagIds}", shippingHandoverFormId, string.Join(",", bagTagIds));
            try
            {
                var relations = new List<ShippingHandoverFormBagTagEntity>();
                
                foreach (var bagTagId in bagTagIds)
                {
                    // 检查袋牌是否已关联
                    if (await _repository.ExistsByBagTagIdAsync(bagTagId))
                    {
                        _logger.LogWarning("Bag tag {BagTagId} is already associated with another shipping handover form", bagTagId);
                        continue;
                    }

                    // 获取袋牌信息
                    var bagTag = await _bagTagRepository.GetByIdAsync(bagTagId);
                    if (bagTag == null)
                    {
                        _logger.LogWarning("Bag tag {BagTagId} not found", bagTagId);
                        continue;
                    }

                    // 创建关联记录
                    var relation = new ShippingHandoverFormBagTagEntity
                    {
                        ShippingHandoverFormId = shippingHandoverFormId,
                        BagTagId = bagTagId,
                        TagNumber = bagTag.TagNumber
                    };
                    relations.Add(relation);
                }

                if (relations.Count > 0)
                {
                    return await _repository.InsertBatchAsync(relations);
                }
                return 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error associating bag tags to shipping handover form");
                throw;
            }
        }

        /// <summary>
        /// 获取出货交接单关联的袋牌列表
        /// </summary>
        /// <param name="shippingHandoverFormId">出货交接单ID</param>
        /// <returns>袋牌列表</returns>
        public async Task<List<BagTagEntity>> GetAssociatedBagTagsAsync(int shippingHandoverFormId)
        {
            _logger.LogInformation("Getting associated bag tags for shipping handover form: {ShippingHandoverFormId}", shippingHandoverFormId);
            try
            {
                var relations = await _repository.GetByShippingHandoverFormIdAsync(shippingHandoverFormId);
                var bagTags = new List<BagTagEntity>();

                foreach (var relation in relations)
                {
                    var bagTag = await _bagTagRepository.GetByIdAsync(relation.BagTagId);
                    if (bagTag != null)
                    {
                        // 查询袋牌关联的运单数量
                        var waybills = await _bagTagRepository.GetWaybillsByTagNumberAsync(bagTag.TagNumber);
                        bagTag.WaybillCount = waybills.Count;

                        bagTags.Add(bagTag);
                    }
                }

                return bagTags;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting associated bag tags");
                throw;
            }
        }

        /// <summary>
        /// 从出货交接单中移除袋牌
        /// </summary>
        /// <param name="relationId">关联ID</param>
        /// <returns>影响行数</returns>
        public async Task<int> RemoveBagTagAsync(int relationId)
        {
            _logger.LogInformation("Removing bag tag association: {RelationId}", relationId);
            try
            {
                return await _repository.DeleteAsync(relationId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error removing bag tag association");
                throw;
            }
        }

        /// <summary>
        /// 清空出货交接单的所有袋牌关联
        /// </summary>
        /// <param name="shippingHandoverFormId">出货交接单ID</param>
        /// <returns>影响行数</returns>
        public async Task<int> ClearBagTagsAsync(int shippingHandoverFormId)
        {
            _logger.LogInformation("Clearing all bag tag associations for shipping handover form: {ShippingHandoverFormId}", shippingHandoverFormId);
            try
            {
                return await _repository.DeleteByShippingHandoverFormIdAsync(shippingHandoverFormId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error clearing bag tag associations");
                throw;
            }
        }

        /// <summary>
        /// 统计出货交接单的袋牌数量和包裹数量
        /// </summary>
        /// <param name="shippingHandoverFormId">出货交接单ID</param>
        /// <returns>袋牌数量和包裹数量</returns>
        public async Task<(int BagTagCount, int PackageCount)> CountBagTagsAndPackagesAsync(int shippingHandoverFormId)
        {
            _logger.LogInformation("Counting bag tags and packages for shipping handover form: {ShippingHandoverFormId}", shippingHandoverFormId);
            try
            {
                var bagTags = await GetAssociatedBagTagsAsync(shippingHandoverFormId);
                var bagTagCount = bagTags.Count;
                
                // 统计每个袋牌中的包裹数量（通过查询关联的运单）
                var packageCount = 0;
                foreach (var bagTag in bagTags)
                {
                    var waybills = await _bagTagRepository.GetWaybillsByTagNumberAsync(bagTag.TagNumber);
                    packageCount += waybills.Count;
                }
                
                return (bagTagCount, packageCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error counting bag tags and packages");
                throw;
            }
        }

        /// <summary>
        /// 检查袋牌是否已关联到出货交接单
        /// </summary>
        /// <param name="bagTagId">袋牌ID</param>
        /// <returns>是否已关联</returns>
        public async Task<bool> IsBagTagAssociatedAsync(int bagTagId)
        {
            _logger.LogInformation("Checking if bag tag is associated: {BagTagId}", bagTagId);
            try
            {
                return await _repository.ExistsByBagTagIdAsync(bagTagId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking if bag tag is associated");
                throw;
            }
        }

        /// <summary>
        /// 通过袋牌号关联袋牌到出货交接单
        /// </summary>
        /// <param name="shippingHandoverFormId">出货交接单ID</param>
        /// <param name="bagTagNumbers">袋牌号列表</param>
        /// <returns>影响行数</returns>
        public async Task<int> AssociateBagTagsByNumberAsync(int shippingHandoverFormId, List<string> bagTagNumbers)
        {
            _logger.LogInformation("Associating bag tags by number to shipping handover form: {ShippingHandoverFormId}, BagTagNumbers: {BagTagNumbers}", shippingHandoverFormId, string.Join(",", bagTagNumbers));
            try
            {
                var relations = new List<ShippingHandoverFormBagTagEntity>();
                
                foreach (var bagTagNumber in bagTagNumbers)
                {
                    // 获取袋牌信息
                    var bagTag = await _bagTagRepository.GetByTagNumberAsync(bagTagNumber);
                    if (bagTag == null)
                    {
                        _logger.LogWarning("Bag tag with number {BagTagNumber} not found", bagTagNumber);
                        continue;
                    }

                    // 检查袋牌是否已关联
                    if (await _repository.ExistsByBagTagIdAsync(bagTag.Id))
                    {
                        _logger.LogWarning("Bag tag {BagTagNumber} is already associated with another shipping handover form", bagTagNumber);
                        continue;
                    }

                    // 创建关联记录
                    var relation = new ShippingHandoverFormBagTagEntity
                    {
                        ShippingHandoverFormId = shippingHandoverFormId,
                        BagTagId = bagTag.Id,
                        TagNumber = bagTag.TagNumber
                    };
                    relations.Add(relation);

                    // 如果袋牌是非关闭状态，关闭袋牌
                    if (bagTag.Status != "Closed")
                    {
                        _logger.LogInformation("Closing bag tag {BagTagNumber} with status {Status}", bagTagNumber, bagTag.Status);
                        bagTag.Status = "Closed";
                        bagTag.ClosedAt = System.DateTime.UtcNow;
                        await _bagTagRepository.UpdateAsync(bagTag);
                    }
                }

                if (relations.Count > 0)
                {
                    return await _repository.InsertBatchAsync(relations);
                }
                return 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error associating bag tags by number to shipping handover form");
                throw;
            }
        }
    }
}