using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Caching.Memory;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi.Attributes;
using NPP.SmartSchedue.Api.Contracts.Services.Integration;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
using NPP.SmartSchedue.Api.Repositories.Work;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel;
using NPP.SmartSchedue.Api.Contracts.Services.Time;
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Internal;
using NPP.SmartSchedue.Api.Services.Integration.Algorithms;
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel.Output;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Output;
using NPP.SmartSchedue.Api.Contracts.Services.Work;
using NPP.SmartSchedue.Api.Contracts.Services.Work.Output;
using ShiftRuleValidationResult = NPP.SmartSchedue.Api.Contracts.Services.Integration.Internal.ShiftRuleValidationResult;

namespace NPP.SmartSchedue.Api.Services.Integration
{
    /// <summary>
    /// 全局优化人员分配服务
    /// 基于遗传算法和基尼系数的智能全局优化分配
    /// </summary>
    [DynamicApi(Area = "app")]
    public partial class GlobalPersonnelAllocationService : BaseService, IGlobalPersonnelAllocationService
    {
        private readonly ILogger<GlobalPersonnelAllocationService> _logger;
        private readonly IMemoryCache _memoryCache;
        private readonly ActivitySource _activitySource;

        /// <summary>
        /// 输入验证引擎 - 专门处理第一阶段的输入验证和数据准备
        /// </summary>
        private readonly InputValidationEngine _inputValidationEngine;

        /// <summary>
        /// 上下文构建引擎 - 专门处理第二阶段的上下文构建和性能优化
        /// </summary>
        private readonly ContextBuilderEngine _contextBuilderEngine;

        /// <summary>
        /// 全局优化引擎 - 专门处理第三阶段的遗传算法优化和结果处理
        /// </summary>
        private readonly GlobalOptimizationEngine _optimizationEngine;

        /// <summary>
        /// 人员ID到姓名的映射缓存 - 避免重复查询，提高性能
        /// </summary>
        private readonly Dictionary<long, string> _personnelNameCache = new();

        /// <summary>
        /// 当前全局分配上下文 - 存储预加载的数据，避免重复数据库查询
        /// 业务用途：在分配过程中提供缓存的班次规则、人员历史等数据
        /// 生命周期：在AllocatePersonnelGloballyAsync方法执行期间有效
        /// </summary>
        private GlobalAllocationContext? _currentAllocationContext;

        public GlobalPersonnelAllocationService(
           
            ILogger<GlobalPersonnelAllocationService> logger,
            IMemoryCache memoryCache,
            InputValidationEngine inputValidationEngine,
            ContextBuilderEngine contextBuilderEngine,
            GlobalOptimizationEngine optimizationEngine)
        {
            _logger = logger;
            _memoryCache = memoryCache;
            _inputValidationEngine =
                inputValidationEngine ?? throw new ArgumentNullException(nameof(inputValidationEngine));
            _contextBuilderEngine =
                contextBuilderEngine ?? throw new ArgumentNullException(nameof(contextBuilderEngine));
            _optimizationEngine = optimizationEngine ?? throw new ArgumentNullException(nameof(optimizationEngine));

            _activitySource = new ActivitySource("NPP.SmartSchedule.GlobalAllocation");
        }

        /// <summary>
        /// 全局优化人员分配 - 核心业务方法
        /// 业务逻辑：使用遗传算法对未分配人员的任务进行全局优化分配
        /// 算法流程：输入验证 → 构建分配上下文 → 执行遗传算法优化 → 智能协商处理冲突 → 返回优化结果
        /// 性能目标：30秒内完成分配，基尼系数小于0.3，约束满足率大于90%
        /// </summary>
        /// <param name="input">全局分配输入参数，包含待分配任务、排除人员、优化配置</param>
        /// <returns>全局分配结果，包含成功匹配、失败项、公平性分析、协商操作等</returns>
        [HttpPost]
        public async Task<GlobalAllocationResult> AllocatePersonnelGloballyAsync(GlobalAllocationInput input)
        {
            using var activity = _activitySource?.StartActivity("GlobalAllocation");
            var stopwatch = Stopwatch.StartNew();

            try
            {
                var taskCount = input.Tasks?.Count ?? input.TaskIds?.Count ?? 0;
                _logger.LogInformation("🚀 开始全局优化人员分配，任务数量：{TaskCount}，排除人员：{ExcludedCount}",
                    taskCount, input.ExcludedPersonnelIds?.Count ?? 0);

                // 【重构完成】第一阶段：使用专门的输入验证引擎处理输入验证和数据准备
                _logger.LogInformation("📋 阶段1：开始输入验证和数据准备（使用InputValidationEngine）");
                var validationResult = await _inputValidationEngine.ValidateAndPrepareAsync(input);
                if (!validationResult.IsValid)
                {
                    _logger.LogError("❌ 输入验证失败：{ErrorMessage}", validationResult.ErrorMessage);
                    return CreateFailureResult(validationResult.ErrorMessage);
                }

                _logger.LogInformation("✅ 输入验证通过，有效任务数：{ValidTaskCount}（Engine处理）", validationResult.WorkOrders.Count);

                // 【重构完成】第二阶段：使用专门的上下文构建引擎构建全局分配上下文
                _logger.LogInformation("🏗️ 阶段2：开始构建全局分配上下文（使用ContextBuilderEngine）");
                var context = await _contextBuilderEngine.BuildContextAsync(input, validationResult.WorkOrders);

                _logger.LogInformation(
                    "📊 分配上下文构建完成 - 任务数：{TaskCount}，可用人员：{PersonnelCount}，预筛选结果：{PrefilterCount}（Engine处理）",
                    context.Tasks.Count, context.AvailablePersonnel.Count, context.PrefilterResults.Count);

                // 【性能关键修复】：设置当前分配上下文，供班次规则查询优化使用
                _currentAllocationContext = context;

                activity?.SetTag("task.count", context.Tasks.Count);
                activity?.SetTag("personnel.pool.size", context.AvailablePersonnel.Count);
                activity?.SetTag("algorithm.population.size", input.OptimizationConfig.PopulationSize);

                // 第三阶段：执行全局优化算法
                _logger.LogInformation("🧬 阶段3：开始执行全局优化算法");
                
                // 【关键修复】初始化人员姓名缓存，确保结果显示真实姓名而非"人员_ID"格式
                var personnelNameMapping = context.AvailablePersonnel.ToDictionary(p => p.Id, p => p.Name);
                _optimizationEngine.SetPersonnelNameCache(personnelNameMapping);
                
                var optimizationResult = await _optimizationEngine.ExecuteOptimizationAsync(context);

                stopwatch.Stop();
                activity?.SetTag("execution.time.ms", stopwatch.ElapsedMilliseconds);
                activity?.SetTag("allocation.success", optimizationResult.IsSuccess);

                if (optimizationResult.IsSuccess)
                {
                    _logger.LogInformation("🎉 全局优化分配成功！耗时：{ElapsedMs}ms，成功分配：{SuccessCount}个任务，失败：{FailCount}个任务",
                        stopwatch.ElapsedMilliseconds, optimizationResult.SuccessfulMatches?.Count ?? 0,
                        optimizationResult.FailedAllocations?.Count ?? 0);
                }
                else
                {
                    _logger.LogWarning("⚠️ 全局优化分配未完全成功，耗时：{ElapsedMs}ms，原因：{Reason}",
                        stopwatch.ElapsedMilliseconds, optimizationResult.AllocationSummary ?? "未知原因");
                }

                return optimizationResult;
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                if (activity != null)
                {
                    activity.SetStatus(ActivityStatusCode.Error, ex.Message);
                }

                _logger.LogError(ex, "全局优化人员分配异常，耗时：{ElapsedMs}ms", stopwatch.ElapsedMilliseconds);
                return CreateFailureResult($"系统异常：{ex.Message}");
            }
            finally
            {
                // 【内存管理】：清理当前分配上下文，避免内存泄漏
                _currentAllocationContext = null;
            }
        }

       
        #region 辅助方法

        /// <summary>
        /// 创建失败结果 - 错误处理工具方法
        /// 业务逻辑：当输入验证或系统异常时，统一创建格式化的失败响应
        /// 设计目的：保证API响应的一致性，提供明确的错误信息
        /// </summary>
        /// <param name="errorMessage">错误消息</param>
        /// <returns>失败的全局分配结果</returns>
        private GlobalAllocationResult CreateFailureResult(string errorMessage)
        {
            return new GlobalAllocationResult
            {
                IsSuccess = false,
                AllocationSummary = $"全局分配失败：{errorMessage}",
                ProcessingDetails = errorMessage
            };
        }

        #endregion
    }
}