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

namespace NPP.SmartSchedue.Api.Services.Work;

/// <summary>
/// 工作任务服务
/// </summary>
[DynamicApi(Area = "app")]
public class WorkOrderService : BaseService, IWorkOrderService, IDynamicApi
{
    private readonly WorkOrderRepository _workOrderRepository;
    private readonly WorkOrderFLPersonnelRepository _workOrderFlPersonnelRepository;
    private readonly IEmployeeLeaveService _employeeLeaveService;
    private readonly IPersonnelWorkLimitService _personnelWorkLimitService;
    private readonly IShiftService _shiftService;
    private readonly IShiftRuleMappingService _shiftRuleMappingService;
    private readonly IShiftRuleService _shiftRuleService;
    private readonly IShiftUnavailabilityService _shiftUnavailabilityService;
    private readonly ILogger<WorkOrderService> _logger;

    public WorkOrderService(
        WorkOrderRepository workOrderRepository,
        WorkOrderFLPersonnelRepository workOrderFlPersonnelRepository,
        IEmployeeLeaveService employeeLeaveService,
        IPersonnelWorkLimitService personnelWorkLimitService,
        IShiftService shiftService,
        IShiftRuleMappingService shiftRuleMappingService,
        IShiftRuleService shiftRuleService,
        IShiftUnavailabilityService shiftUnavailabilityService,
        ILogger<WorkOrderService> logger)
    {
        _workOrderRepository = workOrderRepository;
        _workOrderFlPersonnelRepository = workOrderFlPersonnelRepository;
        _employeeLeaveService = employeeLeaveService;
        _personnelWorkLimitService = personnelWorkLimitService;
        _shiftService = shiftService;
        _shiftRuleMappingService = shiftRuleMappingService;
        _shiftRuleService = shiftRuleService;
        _shiftUnavailabilityService = shiftUnavailabilityService;
        _logger = logger;
    }

    /// <summary>
    /// 查询
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<WorkOrderGetOutput> GetAsync(long id)
    {
        var output = await _workOrderRepository.Select
            .WhereDynamic(id)
            .ToOneAsync<WorkOrderGetOutput>();

        if (output != null)
        {
            // 获取关联的FL人员信息
            var flPersonnels = await _workOrderFlPersonnelRepository.Select
                .Where(a => a.WorkOrderId == id)
                .ToListAsync();

            output.FLPersonnels = flPersonnels.Select(fp => new FLPersonnelInfo
            {
                FLPersonnelId = fp.FLPersonnelId,
                FLPersonnelName = fp.FLPersonnelName
            }).ToList();
        }

        return output;
    }

    /// <summary>
    /// 查询分页
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<PageOutput<WorkOrderGetPageOutput>> GetPageAsync(PageInput<WorkOrderGetPageInput> input)
    {
        var list = await _workOrderRepository.Select
            .WhereIf(!string.IsNullOrEmpty(input.Filter?.ProjectNumber),
                a => a.ProjectNumber.Contains(input.Filter.ProjectNumber))
            .WhereIf(!string.IsNullOrEmpty(input.Filter?.WorkOrderCode),
                a => a.WorkOrderCode.Contains(input.Filter.WorkOrderCode))
            .WhereIf(input.Filter?.Status.HasValue == true,
                a => a.Status == (int)(WorkOrderStatusEnum)input.Filter.Status.Value)
            .WhereIf(input.Filter?.StartDate.HasValue == true, a => a.WorkOrderDate >= input.Filter.StartDate.Value)
            .WhereIf(input.Filter?.EndDate.HasValue == true, a => a.WorkOrderDate <= input.Filter.EndDate.Value)
            .Count(out var total)
            .OrderByDescending(a => a.Id)
            .Page(input.CurrentPage, input.PageSize)
            .ToListAsync<WorkOrderGetPageOutput>();

        // 为分页结果添加FL人员信息
        if (list?.Any() == true)
        {
            var workOrderIds = list.Select(x => x.Id).ToList();
            var flPersonnelsList = await _workOrderFlPersonnelRepository.Select
                .Where(a => workOrderIds.Contains(a.WorkOrderId))
                .ToListAsync();

            var flPersonnelsDict = flPersonnelsList
                .GroupBy(fp => fp.WorkOrderId)
                .ToDictionary(
                    g => g.Key,
                    g => g.Select(fp => new FLPersonnelInfo
                    {
                        FLPersonnelId = fp.FLPersonnelId,
                        FLPersonnelName = fp.FLPersonnelName
                    }).ToList()
                );

            foreach (var item in list)
            {
                if (flPersonnelsDict.TryGetValue(item.Id, out var flPersonnels))
                {
                    item.FLPersonnels = flPersonnels;
                }
                else
                {
                    item.FLPersonnels = new List<FLPersonnelInfo>();
                }
            }
        }

        var data = new PageOutput<WorkOrderGetPageOutput>()
        {
            List = list,
            Total = total
        };

        return data;
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<long> AddAsync(WorkOrderAddInput input)
    {
        return await AddSingleWorkOrderAsync(input);
    }

    /// <summary>
    /// 批量添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<BatchWorkOrderAddOutput> BatchAddAsync(BatchWorkOrderAddInput input)
    {
        var result = new BatchWorkOrderAddOutput
        {
            TotalCount = input.WorkOrders?.Count ?? 0
        };

        if (input.WorkOrders?.Any() != true)
        {
            result.IsSuccess = false;
            result.Message = "工作任务列表不能为空";
            return result;
        }

        var successIds = new List<long>();
        var failedItems = new List<BatchWorkOrderError>();

        // 开始批量处理
        for (int i = 0; i < input.WorkOrders.Count; i++)
        {
            var workOrder = input.WorkOrders[i];

            try
            {
                // 添加单个任务
                var workOrderId = await AddSingleWorkOrderAsync(workOrder);
                successIds.Add(workOrderId);
            }
            catch (Exception ex)
            {
                failedItems.Add(new BatchWorkOrderError
                {
                    Index = i,
                    WorkOrderCode = $"{workOrder.ProjectNumber}_{workOrder.ShiftCode}_{workOrder.ProcessCode}" ??
                                    $"第{i + 1}个任务",
                    ErrorMessage = ex.Message,
                    ErrorDetail = ex.ToString()
                });

                // 如果启用失败回滚，则回滚已添加的任务
                if (input.RollbackOnFailure)
                {
                    foreach (var successId in successIds)
                    {
                        try
                        {
                            await DeleteAsync(successId);
                        }
                        catch
                        {
                            // 回滚失败，记录日志但不影响主流程
                        }
                    }

                    result.IsSuccess = false;
                    result.Message = $"批量添加失败，已回滚所有操作。错误: {ex.Message}";
                    return result;
                }
            }
        }

        // 设置结果
        result.SuccessIds = successIds;
        result.FailedItems = failedItems;
        result.SuccessCount = successIds.Count;
        result.FailedCount = failedItems.Count;
        result.IsSuccess = result.SuccessCount > 0;
        result.Message = $"批量添加完成。成功: {result.SuccessCount}，失败: {result.FailedCount}";

        return result;
    }

    /// <summary>
    /// 修改
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task UpdateAsync(WorkOrderUpdateInput input)
    {
        var entity = await _workOrderRepository.GetAsync(input.Id);
        Mapper.Map(input, entity);

        await ConvertWorkOrderShift(entity);
        await _workOrderRepository.UpdateAsync(entity);

        // 更新FL人员关联
        await UpdateWorkOrderFLPersonnelsAsync(input.Id, input.FLPersonnels ?? new List<FLPersonnelInfo>());
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task DeleteAsync(long id)
    {
        // 删除FL人员关联
        await _workOrderFlPersonnelRepository.DeleteAsync(a => a.WorkOrderId == id);

        // 删除工作任务
        await _workOrderRepository.DeleteAsync(id);
    }

    /// <summary>
    /// 软删除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task SoftDeleteAsync(long id)
    {
        await _workOrderRepository.SoftDeleteAsync(id);
    }

    /// <summary>
    /// 批量软删除
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task BatchSoftDeleteAsync(long[] ids)
    {
        await _workOrderRepository.SoftDeleteAsync(ids);
    }

    /// <summary>
    /// 更新任务状态
    /// </summary>
    /// <param name="id"></param>
    /// <param name="status"></param>
    /// <returns></returns>
    public async Task UpdateStatusAsync(long id, WorkOrderStatusEnum status)
    {
        var entity = await _workOrderRepository.GetAsync(id);
        if (entity != null)
        {
            entity.Status = (int)status;
            await _workOrderRepository.UpdateAsync(entity);
        }
    }

    /// <summary>
    /// 开始任务
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task StartAsync(long id)
    {
        var entity = await _workOrderRepository.GetAsync(id);
        if (entity != null)
        {
            entity.Status = (int)WorkOrderStatusEnum.InProgress;
            entity.ActualStartTime = DateTime.Now;
            await _workOrderRepository.UpdateAsync(entity);
        }
    }

    /// <summary>
    /// 完成任务
    /// </summary>
    /// <param name="id"></param>
    /// <param name="actualWorkHours"></param>
    /// <returns></returns>
    public async Task CompleteAsync(long id, decimal? actualWorkHours = null)
    {
        var entity = await _workOrderRepository.GetAsync(id);
        if (entity != null)
        {
            entity.Status = (int)WorkOrderStatusEnum.Completed;
            entity.ActualEndTime = DateTime.Now;

            if (actualWorkHours.HasValue)
            {
                entity.ActualWorkHours = actualWorkHours.Value;
            }
            else if (entity.ActualStartTime.HasValue)
            {
                // 自动计算工时
                var timeSpan = DateTime.Now - entity.ActualStartTime.Value;
                entity.ActualWorkHours = (decimal)timeSpan.TotalHours;
            }

            await _workOrderRepository.UpdateAsync(entity);
        }
    }

    #region 私有方法

    /// <summary>
    /// 添加单个工作任务（内部方法）
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    private async Task<long> AddSingleWorkOrderAsync(WorkOrderAddInput input)
    {
        var result = new WorkOrderEntity();

        for (int i = 1; i <= input.RequiredPersonnel; i++)
        {
            var entity = Mapper.Map<WorkOrderEntity>(input);

            // 生成任务代码：项目号_班次code_工序code
            if (string.IsNullOrEmpty(entity.WorkOrderCode))
            {
                entity.WorkOrderCode = $"{entity.ProjectNumber}_{entity.ShiftCode}_{entity.ProcessCode}";
            }

            // 设置默认状态
            if (entity.Status == 0)
            {
                entity.Status = (int)WorkOrderStatusEnum.PendingSubmit;
            }

            if (input.RequiredPersonnel > 1 && i == 1)
            {
                entity.NeedPostHead = true;
            }

            // 获取任务班次信息
            await ConvertWorkOrderShift(entity);
            result = await _workOrderRepository.InsertAsync(entity);

            // 添加FL人员关联
            if (input.FLPersonnels?.Any() == true)
            {
                await AddWorkOrderFLPersonnelsAsync(result.Id, input.FLPersonnels);
            }
        }

        return result.Id;
    }

    /// <summary>
    /// 添加工作任务FL人员关联
    /// </summary>
    /// <param name="workOrderId"></param>
    /// <param name="flPersonnels"></param>
    /// <returns></returns>
    private async Task AddWorkOrderFLPersonnelsAsync(long workOrderId, List<FLPersonnelInfo> flPersonnels)
    {
        if (flPersonnels?.Any() == true)
        {
            var entities = flPersonnels.Select(fp => new WorkOrderFLPersonnelEntity
            {
                WorkOrderId = workOrderId,
                FLPersonnelId = fp.FLPersonnelId,
                FLPersonnelName = fp.FLPersonnelName,
                CreatedTime = DateTime.Now
            }).ToList();

            await _workOrderFlPersonnelRepository.InsertAsync(entities);
        }
    }

    /// <summary>
    /// 更新工作任务FL人员关联
    /// </summary>
    /// <param name="workOrderId"></param>
    /// <param name="flPersonnels"></param>
    private async Task UpdateWorkOrderFLPersonnelsAsync(long workOrderId, List<FLPersonnelInfo> flPersonnels)
    {
        // 删除现有关联
        await _workOrderFlPersonnelRepository.DeleteAsync(a => a.WorkOrderId == workOrderId);

        // 添加新关联
        await AddWorkOrderFLPersonnelsAsync(workOrderId, flPersonnels);
    }

    /// <summary>
    /// 转换工作任务班次信息，计算计划开始和结束时间
    /// 【核心业务逻辑】：将班次的时间配置与任务日期结合，生成具体的执行时间段
    /// 【深度思考】：该方法解决了班次时间模板与具体任务执行日期的映射问题，
    /// 特别处理了跨天班次的复杂场景，确保时间计算的准确性
    /// </summary>
    /// <param name="workOrderEntity">待转换的工作任务实体</param>
    /// <returns>转换后的工作任务实体，包含计算好的计划开始和结束时间</returns>
    public async Task<WorkOrderEntity> ConvertWorkOrderShift(WorkOrderEntity workOrderEntity)
    {
        // 【业务逻辑】：根据任务的班次ID获取班次定义信息
        // 班次定义包含: StartTime、EndTime、班次名称等基础配置
        var shift = await _shiftService.GetAsync(workOrderEntity.ShiftId ?? 0);
        if (shift != null)
        {
            // 【时间计算核心】：将任务执行日期与班次时间模板结合
            // 关键设计：只取日期部分，避免时间部分干扰班次时间的准确计算
            var workDate = workOrderEntity.WorkOrderDate.Date; // 取日期部分，确保时间为00:00:00

            // 【计划时间生成】：组合任务日期和班次时间，生成具体的执行时间点
            // 例：任务日期2024-01-15 + 班次开始08:00 = 2024-01-15 08:00:00
            workOrderEntity.PlannedStartTime = workDate.Add(shift.StartTime);
            workOrderEntity.PlannedEndTime = workDate.Add(shift.EndTime);

            // 【跨天班次特殊处理】：处理夜班等跨越午夜的班次场景
            // 深度业务思考：如夜班22:00-06:00，结束时间小于开始时间表示跨天
            // 解决方案：将结束时间推迟一天，确保时间逻辑正确
            // 示例：2024-01-15 22:00 - 2024-01-16 06:00
            if (shift.EndTime < shift.StartTime)
            {
                // 跨天班次：结束时间需要加一天
                // 业务场景：夜班从今天22:00工作到明天06:00
                workOrderEntity.PlannedEndTime = workOrderEntity.PlannedEndTime.AddDays(1);
            }
        }
        // 【异常处理】：如果班次信息不存在，保持原有的时间设置
        // 这种设计避免了因班次配置缺失而导致任务创建失败的情况

        return workOrderEntity;
    }

    #endregion

    public async Task<Dictionary<long, int>> GetPendingSubmitCountByCreatorAsync()
    {
        var query = _workOrderRepository.Select
            .Where(w => w.Status == (int)WorkOrderStatusEnum.PendingSubmit)
            .GroupBy(w => new { w.CreatedUserId })
            .ToList<(long CreatedUserId, int Cnt)>(a => new ValueTuple<long, int>(a.Key.CreatedUserId ?? 0, a.Count()));

        var dict = query
            .Where(x => x.CreatedUserId > 0)
            .GroupBy(x => x.CreatedUserId)
            .ToDictionary(g => g.Key, g => g.Sum(x => x.Cnt));
        return dict;
    }

    #region 任务自检功能

    /// <summary>
    /// 单个任务自检
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<WorkOrderValidationOutput> ValidateWorkOrderAsync(SingleWorkOrderValidationInput input)
    {
        var workOrder = await _workOrderRepository.GetAsync(input.WorkOrderId);
        if (workOrder == null)
        {
            return new WorkOrderValidationOutput
            {
                WorkOrderId = input.WorkOrderId,
                IsValid = false,
                Errors = new List<WorkOrderValidationError>
                {
                    new WorkOrderValidationError
                    {
                        ErrorType = ValidationErrorType.TaskTimeConflict,
                        Message = "任务不存在"
                    }
                }
            };
        }

        var result = new WorkOrderValidationOutput
        {
            WorkOrderId = input.WorkOrderId,
            WorkOrderCode = workOrder.WorkOrderCode,
            IsValid = true
        };

        // 如果任务已分配实施人员，则检查人员空闲状态
        if (workOrder.AssignedPersonnelId.HasValue)
        {
            // 检查分配人员的空闲状态
            var personnelResult = await CheckPersonnelAvailabilityWithBatchContextAsync(
                workOrder.AssignedPersonnelId.Value,
                workOrder.AssignedPersonnelName ?? $"人员{workOrder.AssignedPersonnelId}",
                workOrder,
                new List<WorkOrderEntity>() { workOrder });

            result.PersonnelResults.Add(personnelResult);

            if (!personnelResult.IsAvailable)
            {
                result.IsValid = false;
                // 添加具体的错误信息
                foreach (var detail in personnelResult.ConflictDetails)
                {
                    result.Errors.Add(new WorkOrderValidationError
                    {
                        ErrorType = GetErrorTypeFromDetail(detail),
                        Message = detail,
                        PersonnelId = workOrder.AssignedPersonnelId.Value,
                        PersonnelName = workOrder.AssignedPersonnelName
                    });
                }
            }
        }
        else
        {
            // 任务未分配实施人员，自检通过，但添加信息说明
            result.PersonnelResults.Add(new PersonnelAvailabilityResult
            {
                PersonnelId = 0,
                PersonnelName = "未分配",
                IsAvailable = true,
                ConflictDetails = new List<string> { "任务尚未分配实施人员" }
            });
        }

        // 如果自检通过且需要更新状态为待整合
        if (result.IsValid && input.UpdateStatusToPendingIntegration)
        {
            await UpdateStatusAsync(workOrder.Id, WorkOrderStatusEnum.PendingIntegration);
        }

        return result;
    }

    /// <summary>
    /// 多个任务自检
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<MultipleWorkOrderValidationOutput> ValidateMultipleWorkOrdersAsync(WorkOrderValidationInput input)
    {
        var result = new MultipleWorkOrderValidationOutput
        {
            IsValid = true
        };

        // 获取所有待验证的任务信息（用于上下文计算）
        var allWorkOrders = await _workOrderRepository.Select
            .Where(wo => input.WorkOrderIds.Contains(wo.Id))
            .ToListAsync();

        // 检查每个任务（考虑批次内其他任务的影响）
        foreach (var workOrderId in input.WorkOrderIds)
        {
            var currentWorkOrder = allWorkOrders.FirstOrDefault(wo => wo.Id == workOrderId);
            if (currentWorkOrder == null)
            {
                result.WorkOrderResults.Add(new WorkOrderValidationOutput
                {
                    WorkOrderId = workOrderId,
                    IsValid = false,
                    Errors = new List<NPP.SmartSchedue.Api.Contracts.Services.Work.Output.WorkOrderValidationError>
                    {
                        new NPP.SmartSchedue.Api.Contracts.Services.Work.Output.WorkOrderValidationError
                        {
                            ErrorType = ValidationErrorType.TaskTimeConflict,
                            Message = "任务不存在"
                        }
                    }
                });
                result.IsValid = false;
                continue;
            }

            // 获取批次内其他任务作为上下文
            var batchContext = allWorkOrders.Where(wo => wo.Id != workOrderId).ToList();
            var singleResult = await ValidateWorkOrderWithBatchContextAsync(currentWorkOrder, batchContext);
            result.WorkOrderResults.Add(singleResult);

            if (!singleResult.IsValid)
            {
                result.IsValid = false;
            }
        }

        // 如果所有任务自检通过且需要更新状态为待整合
        if (result.IsValid && input.UpdateStatusToPendingIntegration)
        {
            try
            {
                var updateTasks = new List<Task>();
                foreach (var workOrderId in input.WorkOrderIds)
                {
                    updateTasks.Add(UpdateStatusAsync(workOrderId, WorkOrderStatusEnum.PendingIntegration));
                }

                // 并行执行状态更新，提高性能
                await Task.WhenAll(updateTasks);

                // 验证所有任务状态确实已更新
                var updatedWorkOrders = await _workOrderRepository.Where(wo => input.WorkOrderIds.Contains(wo.Id))
                    .ToListAsync();

                var failedUpdates = updatedWorkOrders
                    .Where(wo => wo.Status != (int)WorkOrderStatusEnum.PendingIntegration)
                    .ToList();

                if (failedUpdates.Any())
                {
                    throw new InvalidOperationException(
                        $"状态更新失败，涉及任务ID: {string.Join(",", failedUpdates.Select(wo => wo.Id))}");
                }

                _logger.LogInformation($"成功批量更新任务状态为待整合，任务数量: {input.WorkOrderIds?.Count ?? 0}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"批量更新任务状态失败，任务ID: {string.Join(",", input.WorkOrderIds ?? new List<long>())}");
                throw new InvalidOperationException($"批量状态更新失败: {ex.Message}", ex);
            }
        }

        return result;
    }

    /// <summary>
    /// 带批次上下文的单任务验证（考虑本批次其他任务的影响）
    /// </summary>
    /// <param name="workOrder">当前任务</param>
    /// <param name="batchContext">批次内其他任务</param>
    /// <returns></returns>
    private async Task<WorkOrderValidationOutput> ValidateWorkOrderWithBatchContextAsync(WorkOrderEntity workOrder,
        List<WorkOrderEntity> batchContext)
    {
        var result = new WorkOrderValidationOutput
        {
            WorkOrderId = workOrder.Id,
            WorkOrderCode = workOrder.WorkOrderCode,
            IsValid = true
        };

        // 如果任务已分配实施人员，则检查人员空闲状态（包含批次上下文）
        if (workOrder.AssignedPersonnelId.HasValue)
        {
            // 检查分配人员的空闲状态（考虑批次上下文）
            var personnelResult = await CheckPersonnelAvailabilityWithBatchContextAsync(
                workOrder.AssignedPersonnelId.Value,
                workOrder.AssignedPersonnelName ?? $"人员{workOrder.AssignedPersonnelId}",
                workOrder,
                batchContext);

            result.PersonnelResults.Add(personnelResult);

            if (!personnelResult.IsAvailable)
            {
                result.IsValid = false;
                // 添加具体的错误信息
                foreach (var detail in personnelResult.ConflictDetails)
                {
                    result.Errors.Add(new NPP.SmartSchedue.Api.Contracts.Services.Work.Output.WorkOrderValidationError
                    {
                        ErrorType = GetErrorTypeFromDetail(detail),
                        Message = detail,
                        PersonnelId = workOrder.AssignedPersonnelId.Value,
                        PersonnelName = workOrder.AssignedPersonnelName
                    });
                }
            }
        }
        else
        {
            // 任务未分配实施人员，自检通过，但添加信息说明
            result.PersonnelResults.Add(new PersonnelAvailabilityResult
            {
                PersonnelId = 0,
                PersonnelName = "未分配",
                IsAvailable = true,
                ConflictDetails = new List<string> { "任务尚未分配实施人员" }
            });
        }

        return result;
    }

    /// <summary>
    /// 带批次上下文的人员空闲状态检查
    /// </summary>
    private async Task<PersonnelAvailabilityResult> CheckPersonnelAvailabilityWithBatchContextAsync(
        long personnelId,
        string personnelName,
        WorkOrderEntity workOrder,
        List<WorkOrderEntity> batchContext)
    {
        var result = new PersonnelAvailabilityResult
        {
            PersonnelId = personnelId,
            PersonnelName = personnelName,
            IsAvailable = true
        };


        var hasLeaveConflict = !await _shiftUnavailabilityService.CheckUnavailablePersonnelByShift(
            workOrder.WorkOrderDate,
            workOrder.ShiftId ?? 0, workOrder.AssignedPersonnelId ?? 0);

        if (hasLeaveConflict)
        {
            result.HasLeaveConflict = true;
            result.IsAvailable = false;
            result.ConflictDetails.Add($"人员 {personnelName} 在任务时间段的班次存在其他意愿");
        }

        // 检查任务时间冲突（包含批次上下文）
        var taskConflicts =
            await CheckTaskTimeConflictsWithBatchContextAsync(personnelId, workOrder, workOrder.PlannedStartTime,
                workOrder.PlannedEndTime,
                batchContext);

        if (taskConflicts.Any())
        {
            result.HasTaskTimeConflict = true;
            result.IsAvailable = false;
            result.ConflictDetails.AddRange(taskConflicts);
        }

        // 检查班次规则冲突（包含批次上下文）
        var shiftRuleConflicts =
            await CheckShiftRuleConflictsWithBatchContextAsync(personnelId, workOrder, workOrder.PlannedStartTime,
                workOrder.PlannedEndTime,
                batchContext);

        if (shiftRuleConflicts.Any())
        {
            result.IsAvailable = false;
            result.ConflictDetails.AddRange(shiftRuleConflicts);
        }
        else
        {
            result.ConflictDetails.Add("班次规则检查：通过");
        }

        return result;
    }

    /// <summary>
    /// 带批次上下文的任务时间冲突检查（包含精确的时间段重叠检查）
    /// </summary>
    private async Task<List<string>> CheckTaskTimeConflictsWithBatchContextAsync(long personnelId,
        WorkOrderEntity workOrder, DateTime workStartTime, DateTime workEndTime, List<WorkOrderEntity> batchContext)
    {
        return await CheckTaskTimeConflictsWithBatchContextAsync(personnelId, workOrder, workStartTime, workEndTime,
            batchContext, null);
    }

    /// <summary>
    /// 带批次上下文和缓存优化的任务时间冲突检查（包含精确的时间段重叠检查）
    /// 【性能优化】：优先使用PersonnelHistoryTasks缓存，避免重复数据库查询
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <param name="workOrder">工作任务</param>
    /// <param name="workStartTime">工作开始时间</param>
    /// <param name="workEndTime">工作结束时间</param>
    /// <param name="batchContext">批次上下文中的其他任务</param>
    /// <param name="personnelHistoryCache">人员历史任务缓存（可选，优先使用缓存避免数据库查询）</param>
    /// <returns>冲突详情列表</returns>
    private async Task<List<string>> CheckTaskTimeConflictsWithBatchContextAsync(long personnelId,
        WorkOrderEntity workOrder, DateTime workStartTime, DateTime workEndTime, List<WorkOrderEntity> batchContext,
        Dictionary<long, List<WorkOrderHistoryItem>>? personnelHistoryCache)
    {
        var conflicts = new List<string>();

        // 获取当前任务的班次信息
        var currentShift = await _shiftService.GetAsync(workOrder.ShiftId ?? 0);
        if (currentShift == null)
        {
            conflicts.Add("当前任务班次信息不存在");
            return conflicts;
        }

        // 1. 检查与数据库历史任务的冲突（包含时间段重叠检查）
        var dbConflictingTasks = await _workOrderRepository.Select
            .Where(wo => wo.AssignedPersonnelId == personnelId)
            .Where(wo => wo.Id != workOrder.Id) // 排除自己
            .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                         wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                         wo.Status == (int)WorkOrderStatusEnum.Completed)
            .ToListAsync();

        foreach (var conflict in dbConflictingTasks)
        {
            // 优化后的时间冲突检查：只检查真正的时间重叠，移除同日期强约束
            // 深度业务思考：不同日期的任务允许分配给同一人员，只要时间段不重叠
            var conflictShift = await _shiftService.GetAsync(conflict.ShiftId ?? 0);
            if (conflictShift != null)
            {
                var conflictStartTime = conflict.WorkOrderDate.Date.Add(conflictShift.StartTime);
                var conflictEndTime = conflict.WorkOrderDate.Date.Add(conflictShift.EndTime);

                // 处理跨天班次：如果结束时间小于开始时间，说明跨天
                if (conflictShift.EndTime < conflictShift.StartTime)
                {
                    conflictEndTime = conflictEndTime.AddDays(1);
                }

                // 精确检查时间段重叠：只有真正时间重叠才算冲突
                if (IsTimeRangeOverlap(workStartTime, workEndTime, conflictStartTime, conflictEndTime))
                {
                    conflicts.Add(
                        $"与数据库任务 '{conflict.WorkOrderCode}' ({conflictShift.Name}: {conflictShift.StartTime:hh\\:mm}-{conflictShift.EndTime:hh\\:mm}) 时间重叠，日期: {conflict.WorkOrderDate:yyyy-MM-dd}");
                }
            }
            else
            {
                // 如果没有班次信息，仍然需要检查同日期冲突作为兜底
                if (conflict.WorkOrderDate.Date == workOrder.WorkOrderDate.Date)
                {
                    conflicts.Add(
                        $"与数据库任务 '{conflict.WorkOrderCode}' 在同一天存在冲突 (日期: {conflict.WorkOrderDate:yyyy-MM-dd})，缺少班次信息无法精确检查");
                }
            }
        }

        // 2. 检查与批次内其他任务的冲突（精确时间段重叠检查）
        foreach (var conflict in
                 batchContext.Where(wo => wo.AssignedPersonnelId == personnelId && wo.Id != workOrder.Id))
        {
            // 优化后的批次内冲突检查：只检查真正的时间重叠，支持不同日期同人员分配
            var conflictShift = await _shiftService.GetAsync(conflict.ShiftId ?? 0);
            if (conflictShift != null)
            {
                var conflictStartTime = conflict.WorkOrderDate.Date.Add(conflictShift.StartTime);
                var conflictEndTime = conflict.WorkOrderDate.Date.Add(conflictShift.EndTime);

                // 处理跨天班次
                if (conflictShift.EndTime < conflictShift.StartTime)
                {
                    conflictEndTime = conflictEndTime.AddDays(1);
                }

                // 精确检查时间段重叠：只有真正时间重叠才算冲突
                if (IsTimeRangeOverlap(workStartTime, workEndTime, conflictStartTime, conflictEndTime))
                {
                    conflicts.Add(
                        $"与批次内任务 '{conflict.WorkOrderCode}' ({conflictShift.Name}: {conflictShift.StartTime:hh\\:mm}-{conflictShift.EndTime:hh\\:mm}) 时间重叠，日期: {conflict.WorkOrderDate:yyyy-MM-dd}");
                }
            }
            else
            {
                // 如果没有班次信息，检查同日期冲突作为兜底
                if (conflict.WorkOrderDate.Date == workOrder.WorkOrderDate.Date)
                {
                    conflicts.Add(
                        $"与批次内任务 '{conflict.WorkOrderCode}' 在同一天存在冲突 (日期: {conflict.WorkOrderDate:yyyy-MM-dd})，缺少班次信息无法精确检查");
                }
            }
        }

        return conflicts;
    }
    
    /// <summary>
    /// 带批次上下文的工作时间限制冲突检查
    /// </summary>
    private async Task<List<string>> CheckWorkLimitConflictsWithBatchContextAsync(long personnelId,
        WorkOrderEntity workOrder, DateTime workStartTime, DateTime workEndTime, List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            // 获取人员工作时间限制设置
            var workLimit = await _personnelWorkLimitService.GetPersonnelWorkLimitAsync(personnelId);
            if (workLimit == null)
            {
                // 如果没有设置工作时间限制，则认为通过
                return conflicts;
            }

            // 检查连续工作天数限制（需要考虑批次内任务的顺序影响）
            if (workLimit.MaxContinuousWorkDays.HasValue)
            {
                var consecutiveDays =
                    await CalculateConsecutiveWorkDaysWithBatchContextAsync(personnelId, workOrder.WorkOrderDate,
                        batchContext);
                if (consecutiveDays >= workLimit.MaxContinuousWorkDays.Value)
                {
                    conflicts.Add($"连续工作 {consecutiveDays} 天超过限制 {workLimit.MaxContinuousWorkDays.Value} 天（包含批次内任务影响）");
                }
            }

            // 检查当周最大排班次数限制（需要考虑批次内同周任务）
            if (workLimit.MaxShiftsPerWeek.HasValue)
            {
                var weekStart = workOrder.WorkOrderDate.Date.AddDays(-(int)workOrder.WorkOrderDate.DayOfWeek);
                var weekEnd = weekStart.AddDays(7);

                // 数据库中的同周任务数量
                var weeklyTaskCount = await _workOrderRepository.Select
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.Id != workOrder.Id)
                    .Where(wo => wo.WorkOrderDate.Date >= weekStart && wo.WorkOrderDate.Date < weekEnd)
                    .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                 wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                 wo.Status == (int)WorkOrderStatusEnum.Completed)
                    .CountAsync();

                // 批次内的同周任务数量（排除当前任务）
                var batchWeeklyTaskCount = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date >= weekStart && wo.WorkOrderDate.Date < weekEnd)
                    .Count();

                // 总数包含当前任务，所以+1
                var totalWeeklyTasks = weeklyTaskCount + batchWeeklyTaskCount + 1;
                if (totalWeeklyTasks > workLimit.MaxShiftsPerWeek.Value)
                {
                    conflicts.Add(
                        $"本周排班次数 {totalWeeklyTasks} 次超过限制 {workLimit.MaxShiftsPerWeek.Value} 次（包含批次内任务 {batchWeeklyTaskCount} 次）");
                }
            }

            // 检查每日工作量限制（整合原跨任务检查的逻辑）
            if (workOrder.EstimatedHours.HasValue && workOrder.EstimatedHours.Value > 0)
            {
                var currentDate = workOrder.WorkOrderDate.Date;

                // 计算数据库中同一天的总工作量
                var dbDailyWorkHours = await _workOrderRepository.Select
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.Id != workOrder.Id)
                    .Where(wo => wo.WorkOrderDate.Date == currentDate)
                    .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                 wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                 wo.Status == (int)WorkOrderStatusEnum.Completed)
                    .Where(wo => wo.EstimatedHours.HasValue && wo.EstimatedHours.Value > 0)
                    .SumAsync(wo => wo.EstimatedHours.Value);

                // 计算批次内同一天的总工作量
                var batchDailyWorkHours = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == currentDate)
                    .Where(wo => wo.EstimatedHours.HasValue && wo.EstimatedHours.Value > 0)
                    .Sum(wo => wo.EstimatedHours.Value);

                // 总工作量 = 数据库 + 批次内 + 当前任务
                var totalDailyWorkHours = dbDailyWorkHours + batchDailyWorkHours + workOrder.EstimatedHours.Value;

                // 假设每日最大工作时间为12小时（可配置化）
                const decimal MaxDailyWorkHours = 12m;

                if (totalDailyWorkHours > MaxDailyWorkHours)
                {
                    var batchTaskCodes = batchContext
                        .Where(wo => wo.AssignedPersonnelId == personnelId)
                        .Where(wo => wo.WorkOrderDate.Date == currentDate)
                        .Select(wo => wo.WorkOrderCode)
                        .ToList();

                    var batchInfo = batchTaskCodes.Any() ? $"（包含批次内任务: {string.Join(", ", batchTaskCodes)}）" : "";

                    conflicts.Add($"每日工作量 {totalDailyWorkHours:F1}小时 超过限制 {MaxDailyWorkHours}小时 {batchInfo}");
                }
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"工作时间限制检查异常: {ex.Message}");
        }

        return conflicts;
    }

    /// <summary>
    /// 带批次上下文的班次规则冲突检查
    /// </summary>
    private async Task<List<string>> CheckShiftRuleConflictsWithBatchContextAsync(long personnelId,
        WorkOrderEntity workOrder, DateTime workStartTime, DateTime workEndTime, List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            var shiftRules = await _shiftRuleService.GetListAsync();

            foreach (var shiftRule in shiftRules)
            {
                if (shiftRule.IsEnabled)
                {
                    // 根据规则类型执行不同的检查逻辑（考虑批次上下文）
                    var ruleConflicts = await ValidateShiftRuleWithBatchContextAsync(personnelId, workOrder, shiftRule,
                        workStartTime, workEndTime, batchContext);

                    if (ruleConflicts.Any())
                    {
                        conflicts.AddRange(ruleConflicts);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"班次规则检查异常: {ex.Message}");
        }

        return conflicts;
    }
    
    /// <summary>
    /// 计算连续工作天数（考虑批次上下文）
    /// </summary>
    private async Task<int> CalculateConsecutiveWorkDaysWithBatchContextAsync(long personnelId, DateTime targetDate,
        List<WorkOrderEntity> batchContext)
    {
        var consecutiveDays = 1; // 包含目标日期

        // 获取批次内该人员的任务，按日期排序
        var personnelBatchTasks = batchContext
            .Where(wo => wo.AssignedPersonnelId == personnelId)
            .OrderBy(wo => wo.WorkOrderDate.Date)
            .ToList();

        // 创建一个包含批次任务的日期集合
        var batchWorkDates = new HashSet<DateTime>(personnelBatchTasks.Select(t => t.WorkOrderDate.Date));
        batchWorkDates.Add(targetDate.Date); // 包含当前任务日期

        var currentDate = targetDate.Date.AddDays(-1); // 从目标日期前一天开始往前检查

        // 往前检查连续工作天数
        while (true)
        {
            bool hasWork = false;

            // 检查批次内是否有工作
            if (batchWorkDates.Contains(currentDate))
            {
                hasWork = true;
            }
            else
            {
                // 检查数据库中是否有工作
                hasWork = await _workOrderRepository.Select
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == currentDate)
                    .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                 wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                 wo.Status == (int)WorkOrderStatusEnum.Completed)
                    .AnyAsync();
            }

            if (!hasWork)
            {
                break; // 没有工作任务，中断连续天数
            }

            // 检查是否有请假
            var hasLeave = await _employeeLeaveService.HasApprovedLeaveInTimeRangeAsync(
                personnelId,
                currentDate,
                currentDate.AddDays(1));

            if (hasLeave)
            {
                break; // 有请假，中断连续天数
            }

            consecutiveDays++;
            currentDate = currentDate.AddDays(-1);

            // 避免无限循环，最多检查30天
            if (consecutiveDays > 30)
            {
                break;
            }
        }

        return consecutiveDays;
    }

    /// <summary>
    /// 带批次上下文的班次规则验证
    /// </summary>
    private async Task<List<string>> ValidateShiftRuleWithBatchContextAsync(
        long personnelId,
        WorkOrderEntity workOrder,
        ShiftRuleGetPageOutput shiftRule,
        DateTime workStartTime,
        DateTime workEndTime,
        List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            // 根据规则类型执行不同的验证逻辑
            switch (shiftRule?.RuleType)
            {
                case "3": // 一/二班不连续
                    conflicts.AddRange(await ValidateShiftSequenceRuleWithBatchContext(shiftRule.RuleName, personnelId,
                        workOrder, "一", "二", batchContext));
                    break;

                case "4": // 二/三班不连续
                    conflicts.AddRange(await ValidateShiftSequenceRuleWithBatchContext(shiftRule.RuleName, personnelId,
                        workOrder, "二", "三", batchContext));
                    break;

                case "5": // 不能这周日/下周六连
                    conflicts.AddRange(await ValidateSundayToSaturdayRuleWithBatchContext( shiftRule.RuleName,personnelId,
                        workOrder, batchContext));
                    break;

                case "6": // 不能本周六/本周日连
                    conflicts.AddRange(await ValidateSaturdayToSundayRuleWithBatchContext(shiftRule.RuleName,
                        personnelId,
                        workOrder, batchContext));
                    break;

                case "7": // 不能连续7天排班
                    conflicts.AddRange(await ValidateMaxConsecutiveDaysRuleWithBatchContext(shiftRule.RuleName,personnelId,
                        workOrder, 7, batchContext));
                    break;

                case "8": // 三班后一天不排班
                    conflicts.AddRange(await ValidateRestAfterShiftRuleWithBatchContext(shiftRule.RuleName,personnelId,
                        workOrder, "三", batchContext));
                    break;

                case "9": // 二班后一天不排班
                    conflicts.AddRange(await ValidateRestAfterShiftRuleWithBatchContext(shiftRule.RuleName,personnelId,
                        workOrder, "二", batchContext));
                    break;

                default:
                    // 对于未知规则类型，记录警告但不阻止任务
                    break;
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"规则 '{shiftRule?.RuleName}' 验证异常: {ex.Message}");
        }

        return conflicts;
    }

    /// <summary>
    /// 带批次上下文的班次后休息规则验证（示例实现）
    /// </summary>
    private async Task<List<string>> ValidateRestAfterShiftRuleWithBatchContext(string ruleName,
        long personnelId, WorkOrderEntity workOrder, string shiftName, List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            var currentDate = workOrder.WorkOrderDate.Date;

            // 检查前一天是否是指定班次（包含批次上下文和数据库）
            var previousDay = currentDate.AddDays(-1);

            // 先检查批次内是否有前一天的指定班次任务
            var batchPreviousTask = batchContext
                .Where(wo => wo.AssignedPersonnelId == personnelId)
                .Where(wo => wo.WorkOrderDate.Date == previousDay)
                .FirstOrDefault();

            if (batchPreviousTask != null)
            {
                var batchPreviousShift = await _shiftService.GetAsync(batchPreviousTask.ShiftId ?? 0);
                if (batchPreviousShift != null && batchPreviousShift.Name?.Contains(shiftName) == true)
                {
                    conflicts.Add(
                        $"违反批次内班次后休息规则 '{ruleName}': 批次内任务 '{batchPreviousTask.WorkOrderCode}' {shiftName}班后一天不能安排工作");
                }
            }
            else
            {
                // 检查数据库中前一天是否有指定班次
                var dbPreviousTask = await _workOrderRepository.Select
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == previousDay)
                    .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                 wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                 wo.Status == (int)WorkOrderStatusEnum.Completed)
                    .FirstAsync();

                if (dbPreviousTask != null)
                {
                    var dbPreviousShift = await _shiftService.GetAsync(dbPreviousTask.ShiftId ?? 0);
                    if (dbPreviousShift != null && dbPreviousShift.Name?.Contains(shiftName) == true)
                    {
                        conflicts.Add(
                            $"违反班次后休息规则 '{ruleName}': 数据库任务 '{dbPreviousTask.WorkOrderCode}' {shiftName}班后一天不能安排工作");
                    }
                }
            }

            // 检查当前任务是指定班次，确保后一天不排班（包含批次上下文）
            var currentShift = await _shiftService.GetAsync(workOrder.ShiftId ?? 0);
            if (currentShift != null && currentShift.Name?.Contains(shiftName) == true)
            {
                var nextDay = currentDate.AddDays(1);

                // 先检查批次内是否有后一天的任务
                var batchNextTask = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == nextDay)
                    .Any();

                if (batchNextTask)
                {
                    conflicts.Add($"违反批次内班次后休息规则 '{ruleName}': {shiftName}班后一天不能安排批次内任务");
                }
                else
                {
                    // 检查数据库中是否有后一天的任务
                    var dbNextTask = await _workOrderRepository.Select
                        .Where(wo => wo.AssignedPersonnelId == personnelId)
                        .Where(wo => wo.WorkOrderDate.Date == nextDay)
                        .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                     wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                     wo.Status == (int)WorkOrderStatusEnum.Completed)
                        .AnyAsync();

                    if (dbNextTask)
                    {
                        conflicts.Add($"违反班次后休息规则 '{ruleName}': {shiftName}班后一天不能安排工作（与数据库任务冲突）");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"班次后休息规则验证异常: {ex.Message}");
        }

        return conflicts;
    }

    /// <summary>
    /// 带批次上下文的班次连续性规则验证（规则3和4：一/二班不连续以及二/三班不连续）
    /// 深度思考：同一人员同一天不能有冲突的班次安排，需要综合考虑批次内任务和数据库历史任务
    /// </summary>
    private async Task<List<string>> ValidateShiftSequenceRuleWithBatchContext(string ruleName,
        long personnelId, WorkOrderEntity workOrder, string firstShiftName, string secondShiftName,
        List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            var currentShift = await _shiftService.GetAsync(workOrder.ShiftId ?? 0);
            if (currentShift == null) return conflicts;

            var currentDate = workOrder.WorkOrderDate.Date;

            // 检查当前班次是否为规则中的班次之一
            bool currentIsFirstShift = currentShift.Name?.Contains(firstShiftName) == true;
            bool currentIsSecondShift = currentShift.Name?.Contains(secondShiftName) == true;

            if (!currentIsFirstShift && !currentIsSecondShift)
            {
                return conflicts; // 当前班次不是规则关注的班次
            }

            // 1. 检查批次内同一天是否有冲突班次
            var batchSameDayTasks = batchContext
                .Where(wo => wo.AssignedPersonnelId == personnelId)
                .Where(wo => wo.WorkOrderDate.Date == currentDate)
                .ToList();

            foreach (var batchTask in batchSameDayTasks)
            {
                var batchShift = await _shiftService.GetAsync(batchTask.ShiftId ?? 0);
                if (batchShift == null) continue;

                bool batchIsFirstShift = batchShift.Name?.Contains(firstShiftName) == true;
                bool batchIsSecondShift = batchShift.Name?.Contains(secondShiftName) == true;

                // 检查班次冲突：当前是一班且批次内有二班，或当前是二班且批次内有一班
                if ((currentIsFirstShift && batchIsSecondShift) || (currentIsSecondShift && batchIsFirstShift))
                {
                    conflicts.Add(
                        $"违反批次内班次连续性规则 '{ruleName}': 同一天内不能同时安排{firstShiftName}班和{secondShiftName}班 (与批次内任务 '{batchTask.WorkOrderCode}' {batchShift.Name} 冲突)");
                }
            }

            // 2. 检查数据库中同一天是否有冲突班次
            var dbSameDayTasks = await _workOrderRepository.Select
                .Where(wo => wo.AssignedPersonnelId == personnelId)
                .Where(wo => wo.Id != workOrder.Id)
                .Where(wo => wo.WorkOrderDate.Date == currentDate)
                .Where(wo => wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                             wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                             wo.Status == (int)WorkOrderStatusEnum.Completed)
                .ToListAsync();

            foreach (var dbTask in dbSameDayTasks)
            {
                var dbShift = await _shiftService.GetAsync(dbTask.ShiftId ?? 0);
                if (dbShift == null) continue;

                bool dbIsFirstShift = dbShift.Name?.Contains(firstShiftName) == true;
                bool dbIsSecondShift = dbShift.Name?.Contains(secondShiftName) == true;

                // 检查班次冲突
                if ((currentIsFirstShift && dbIsSecondShift) || (currentIsSecondShift && dbIsFirstShift))
                {
                    conflicts.Add(
                        $"违反班次连续性规则 '{ruleName}': 同一天内不能同时安排{firstShiftName}班和{secondShiftName}班 (与数据库任务 '{dbTask.WorkOrderCode}' {dbShift.Name} 冲突)");
                }
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"班次连续性规则验证异常: {ex.Message}");
        }

        return conflicts;
    }

    /// <summary>
    /// 带批次上下文的这周日/下周六连续规则验证（规则5）
    /// 深度思考：防止跨周连续工作，需要检查周日->下周六的7天跨度，批次内可能同时包含这两个时间点的任务
    /// </summary>
    private async Task<List<string>> ValidateSundayToSaturdayRuleWithBatchContext(string  ruleName,
        long personnelId, WorkOrderEntity workOrder, List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            var currentDate = workOrder.WorkOrderDate.Date;

            // 情况1：当前任务是周日，检查下周六是否有排班
            if (currentDate.DayOfWeek == DayOfWeek.Sunday)
            {
                var nextSaturday = currentDate.AddDays(6); // 周日 + 6天 = 下周六

                // 先检查批次内是否有下周六的任务
                var batchNextSaturday = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == nextSaturday)
                    .FirstOrDefault();

                if (batchNextSaturday != null)
                {
                    conflicts.Add(
                        $"违反批次内周日/周六连续规则 '{ruleName}': 不能在这周日和下周六安排工作 (与批次内任务 '{batchNextSaturday.WorkOrderCode}' 冲突)");
                }
                else
                {
                    // 检查数据库中下周六是否有任务
                    var dbNextSaturday = await _workOrderRepository.Select
                        .Where(wo => wo.AssignedPersonnelId == personnelId)
                        .Where(wo => wo.WorkOrderDate.Date == nextSaturday)
                        .Where(wo => wo.Status == (int)WorkOrderStatusEnum.PendingAssignment ||
                                     wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                     wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                     wo.Status == (int)WorkOrderStatusEnum.Completed)
                        .AnyAsync();

                    if (dbNextSaturday)
                    {
                        conflicts.Add($"违反周日/周六连续规则 '{ruleName}': 不能在这周日和下周六安排工作 (与数据库任务冲突)");
                    }
                }
            }

            // 情况2：当前任务是周六，检查上周日是否有排班
            if (currentDate.DayOfWeek == DayOfWeek.Saturday)
            {
                var lastSunday = currentDate.AddDays(-6); // 周六 - 6天 = 上周日

                // 先检查批次内是否有上周日的任务
                var batchLastSunday = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == lastSunday)
                    .FirstOrDefault();

                if (batchLastSunday != null)
                {
                    conflicts.Add(
                        $"违反批次内周日/周六连续规则 '{ruleName}': 不能在上周日和这周六安排工作 (与批次内任务 '{batchLastSunday.WorkOrderCode}' 冲突)");
                }
                else
                {
                    // 检查数据库中上周日是否有任务
                    var dbLastSunday = await _workOrderRepository.Select
                        .Where(wo => wo.AssignedPersonnelId == personnelId)
                        .Where(wo => wo.WorkOrderDate.Date == lastSunday)
                        .Where(wo => wo.Status == (int)WorkOrderStatusEnum.PendingAssignment ||
                                     wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                     wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                     wo.Status == (int)WorkOrderStatusEnum.Completed)
                        .AnyAsync();

                    if (dbLastSunday)
                    {
                        conflicts.Add($"违反周日/周六连续规则 '{ruleName}': 不能在上周日和这周六安排工作 (与数据库任务冲突)");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"周日/周六连续规则验证异常: {ex.Message}");
        }

        return conflicts;
    }

    /// <summary>
    /// 带批次上下文的本周六/本周日连续规则验证（规则6）
    /// 深度思考：防止周末连续工作，批次内可能同时包含同一人员的周六和周日任务
    /// </summary>
    private async Task<List<string>> ValidateSaturdayToSundayRuleWithBatchContext(string ruleName,
        long personnelId, WorkOrderEntity workOrder, List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            var currentDate = workOrder.WorkOrderDate.Date;

            // 情况1：当前是周六，检查周日是否有排班
            if (currentDate.DayOfWeek == DayOfWeek.Saturday)
            {
                var sunday = currentDate.AddDays(1);

                // 先检查批次内是否有周日任务
                var batchSunday = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == sunday)
                    .FirstOrDefault();

                if (batchSunday != null)
                {
                    conflicts.Add(
                        $"违反批次内周六周日连续规则 '{ruleName}': 不能在周六和周日连续安排工作 (与批次内任务 '{batchSunday.WorkOrderCode}' 冲突)");
                }
                else
                {
                    // 检查数据库中周日是否有任务
                    var dbSunday = await _workOrderRepository.Select
                        .Where(wo => wo.AssignedPersonnelId == personnelId)
                        .Where(wo => wo.WorkOrderDate.Date == sunday)
                        .Where(wo => wo.Status == (int)WorkOrderStatusEnum.PendingAssignment ||
                                     wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                     wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                     wo.Status == (int)WorkOrderStatusEnum.Completed)
                        .AnyAsync();

                    if (dbSunday)
                    {
                        conflicts.Add($"违反周六周日连续规则 '{ruleName}': 不能在周六和周日连续安排工作 (与数据库任务冲突)");
                    }
                }
            }

            // 情况2：当前是周日，检查周六是否有排班
            if (currentDate.DayOfWeek == DayOfWeek.Sunday)
            {
                var saturday = currentDate.AddDays(-1);

                // 先检查批次内是否有周六任务
                var batchSaturday = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => wo.WorkOrderDate.Date == saturday)
                    .FirstOrDefault();

                if (batchSaturday != null)
                {
                    conflicts.Add(
                        $"违反批次内周六周日连续规则 '{ruleName}': 不能在周六和周日连续安排工作 (与批次内任务 '{batchSaturday.WorkOrderCode}' 冲突)");
                }
                else
                {
                    // 检查数据库中周六是否有任务
                    var dbSaturday = await _workOrderRepository.Select
                        .Where(wo => wo.AssignedPersonnelId == personnelId)
                        .Where(wo => wo.WorkOrderDate.Date == saturday)
                        .Where(wo => wo.Status == (int)WorkOrderStatusEnum.PendingAssignment ||
                                     wo.Status == (int)WorkOrderStatusEnum.Assigned ||
                                     wo.Status == (int)WorkOrderStatusEnum.InProgress ||
                                     wo.Status == (int)WorkOrderStatusEnum.Completed)
                        .AnyAsync();

                    if (dbSaturday)
                    {
                        conflicts.Add($"违反周六周日连续规则 '{ruleName}': 不能在周六和周日连续安排工作 (与数据库任务冲突)");
                    }
                }
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"周六周日连续规则验证异常: {ex.Message}");
        }

        return conflicts;
    }

    /// <summary>
    /// 带批次上下文的最大连续天数规则验证（规则7：不能连续7天排班）
    /// 深度思考：这是最严格的连续工作限制，需要基于批次+历史数据计算真实的连续工作天数序列
    /// </summary>
    private async Task<List<string>> ValidateMaxConsecutiveDaysRuleWithBatchContext(string ruleName,
         long personnelId, WorkOrderEntity workOrder, int maxDays,
        List<WorkOrderEntity> batchContext)
    {
        var conflicts = new List<string>();

        try
        {
            // 使用已实现的带批次上下文的连续工作天数计算方法
            var consecutiveDays =
                await CalculateConsecutiveWorkDaysWithBatchContextAsync(personnelId, workOrder.WorkOrderDate,
                    batchContext);

            if (consecutiveDays >= maxDays)
            {
                // 获取相关的批次内任务信息用于详细说明
                var relatedBatchTasks = batchContext
                    .Where(wo => wo.AssignedPersonnelId == personnelId)
                    .Where(wo => Math.Abs((wo.WorkOrderDate.Date - workOrder.WorkOrderDate.Date).Days) <= maxDays)
                    .Select(wo => wo.WorkOrderCode)
                    .ToList();

                var batchTasksInfo =
                    relatedBatchTasks.Any() ? $"（涉及批次内任务: {string.Join(", ", relatedBatchTasks)}）" : "";

                conflicts.Add(
                    $"违反连续排班天数限制规则 '{ruleName}': 连续工作 {consecutiveDays} 天超过限制 {maxDays} 天 {batchTasksInfo}");
            }
        }
        catch (Exception ex)
        {
            conflicts.Add($"连续排班天数限制规则验证异常: {ex.Message}");
        }

        return conflicts;
    }
    
    /// <summary>
    /// 检查时间段是否重叠
    /// 修复边界情况处理：相邻时间点不应被视为重叠，支持跨天班次检查
    /// 优化同一天多任务场景：增加缓冲时间机制，提升排班灵活性
    /// </summary>
    /// <param name="start1">第一个时间段的开始时间</param>
    /// <param name="end1">第一个时间段的结束时间</param>
    /// <param name="start2">第二个时间段的开始时间</param>
    /// <param name="end2">第二个时间段的结束时间</param>
    /// <returns>如果时间段重叠返回true，否则返回false</returns>
    private bool IsTimeRangeOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
    {
        // 【新增】缓冲时间配置：允许班次间有30分钟缓冲，支持同一天多任务灵活调度
        const int bufferMinutes = 30;

        // 处理跨天班次：如果结束时间小于开始时间，说明跨天
        var normalizedEnd1 = end1 < start1 ? end1.AddDays(1) : end1;
        var normalizedEnd2 = end2 < start2 ? end2.AddDays(1) : end2;
        var normalizedStart1 = start1;
        var normalizedStart2 = end2 < start2 ? start2.AddDays(-1) : start2;

        // 【优化】应用缓冲时间：在时间比较时减少缓冲时间，允许合理的班次间隔
        var bufferedEnd1 = normalizedEnd1.AddMinutes(-bufferMinutes);
        var bufferedStart1 = normalizedStart1.AddMinutes(bufferMinutes);
        var bufferedEnd2 = normalizedEnd2.AddMinutes(-bufferMinutes);
        var bufferedStart2 = normalizedStart2.AddMinutes(bufferMinutes);

        // 【深度业务思考】：
        // 1. 一班(08:00-17:30) + 二班(14:00-22:00) 原本重叠14:00-17:30（3.5小时）
        // 2. 应用30分钟缓冲后：一班实际到17:00，二班实际从14:30开始
        // 3. 重叠时间减少为14:30-17:00（2.5小时），仍然冲突但影响降低
        // 4. 如果是一班(08:00-14:00) + 二班(14:30-22:00)，则完全无冲突

        // 标准重叠检查：考虑缓冲时间后判断是否仍有重叠
        bool hasOverlap = bufferedStart1 < normalizedEnd2 && normalizedStart2 < bufferedEnd1;

        // 【同一天多任务特殊处理】：如果是同一天且时间接近，允许适度重叠
        if (normalizedStart1.Date == normalizedStart2.Date)
        {
            var overlapMinutes =
                CalculateOverlapMinutes(normalizedStart1, normalizedEnd1, normalizedStart2, normalizedEnd2);

            // 【业务规则】：同一天任务重叠时间小于2小时时，降低冲突等级（警告而非阻止）
            if (overlapMinutes > 0 && overlapMinutes <= 120) // 2小时以内的重叠
            {
                _logger.LogWarning($"同一天任务存在 {overlapMinutes} 分钟重叠，但在可接受范围内（≤2小时）");
                return false; // 不视为严重冲突，允许排班
            }
        }

        return hasOverlap;
    }

    /// <summary>
    /// 计算两个时间段的重叠分钟数
    /// 用于同一天多任务场景的精确重叠时间计算
    /// </summary>
    /// <param name="start1">第一个时间段开始</param>
    /// <param name="end1">第一个时间段结束</param>
    /// <param name="start2">第二个时间段开始</param>
    /// <param name="end2">第二个时间段结束</param>
    /// <returns>重叠分钟数，无重叠返回0</returns>
    private double CalculateOverlapMinutes(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
    {
        var overlapStart = start1 > start2 ? start1 : start2;
        var overlapEnd = end1 < end2 ? end1 : end2;

        if (overlapStart < overlapEnd)
        {
            return (overlapEnd - overlapStart).TotalMinutes;
        }

        return 0; // 无重叠
    }

    /// <summary>
    /// 根据冲突详情获取错误类型
    /// </summary>
    /// <param name="detail"></param>
    /// <returns></returns>
    private ValidationErrorType GetErrorTypeFromDetail(string detail)
    {
        if (detail.Contains("请假"))
            return ValidationErrorType.PersonnelLeaveConflict;
        else if (detail.Contains("任务") && detail.Contains("冲突"))
            return ValidationErrorType.TaskTimeConflict;
        else if (detail.Contains("连续工作") || detail.Contains("工作时间"))
            return ValidationErrorType.ContinuousWorkTimeExceeded;
        else
            return ValidationErrorType.WorkLimitConflict;
    }

    /// <summary>
    /// 根据用户ID查询任务列表
    /// 只返回员工相关的任务状态：已分配、进行中、已完成
    /// </summary>
    /// <param name="userId">用户ID</param>
    /// <returns></returns>
    public async Task<List<WorkOrderGetOutput>> GetByUserIdAsync(long userId)
    {
        var workOrders = await _workOrderRepository.Select
            .Where(a => a.AssignedPersonnelId == userId)
            .Where(a => a.Status == (int)WorkOrderStatusEnum.Assigned ||
                        a.Status == (int)WorkOrderStatusEnum.InProgress ||
                        a.Status == (int)WorkOrderStatusEnum.Completed)
            .OrderBy(a => a.Status == (int)WorkOrderStatusEnum.InProgress ? 0 :
                a.Status == (int)WorkOrderStatusEnum.Assigned ? 1 : 2)
            .OrderByDescending(a => a.WorkOrderDate)
            .OrderByDescending(a => a.Id)
            .ToListAsync<WorkOrderGetOutput>();

        if (workOrders?.Any() == true)
        {
            var workOrderIds = workOrders.Select(x => x.Id).ToList();
            var flPersonnelsList = await _workOrderFlPersonnelRepository.Select
                .Where(a => workOrderIds.Contains(a.WorkOrderId))
                .ToListAsync();

            var flPersonnelsDict = flPersonnelsList
                .GroupBy(fp => fp.WorkOrderId)
                .ToDictionary(
                    g => g.Key,
                    g => g.Select(fp => new FLPersonnelInfo
                    {
                        FLPersonnelId = fp.FLPersonnelId,
                        FLPersonnelName = fp.FLPersonnelName
                    }).ToList()
                );

            foreach (var item in workOrders)
            {
                if (flPersonnelsDict.TryGetValue(item.Id, out var flPersonnels))
                {
                    item.FLPersonnels = flPersonnels;
                }
                else
                {
                    item.FLPersonnels = new List<FLPersonnelInfo>();
                }
            }
        }

        return workOrders ?? new List<WorkOrderGetOutput>();
    }

    #endregion
}