using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel.Output;
using NPP.SmartSchedue.Api.Contracts.Services.Time;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Input;
using NPP.SmartSchedue.Api.Services.Time;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;

namespace NPP.SmartSchedue.Api.Services.Personnel;

/// <summary>
/// 人员综合服务
/// </summary>
[DynamicApi(Area = "app")]
public class PersonService : BaseService, IPersonService, IDynamicApi
{
    private readonly IPersonnelWorkLimitService _personnelWorkLimitService;
    private readonly IPersonnelQualificationService _personnelQualificationService;
    private readonly IQualificationService _qualificationService;
    private readonly IEmployeeLeaveService _employeeLeaveService;
    private readonly IShiftService _shiftService;
    private readonly ShiftUnavailabilityService  _shiftUnavailabilityService;

    public PersonService(
        IPersonnelWorkLimitService personnelWorkLimitService,
        IPersonnelQualificationService personnelQualificationService,
        IQualificationService qualificationService,
        IEmployeeLeaveService employeeLeaveService,
        ShiftUnavailabilityService  shiftUnavailabilityService,
        IShiftService shiftService)
    {
        _personnelWorkLimitService = personnelWorkLimitService;
        _personnelQualificationService = personnelQualificationService;
        _qualificationService = qualificationService;
        _employeeLeaveService = employeeLeaveService;
        _shiftUnavailabilityService = shiftUnavailabilityService;
        _shiftService = shiftService;
    }
    
    /// <summary>
    /// 根据资质IDs、班次ID、工作日期，查询非请假的、有资质的人员
    /// </summary>
    /// <param name="qualificationIds">资质ID列表</param>
    /// <param name="shiftId">班次ID</param>
    /// <param name="workStartTime">工作日期（将结合班次时间计算实际工作时间段）</param>
    /// <returns></returns>
    public async Task<List<AvailablePersonnelOutput>> GetAvailablePersonnelAsync(
        string qualificationIds, 
        long shiftId, 
        DateTime workStartTime)
    {
        var availablePersonnel = new List<AvailablePersonnelOutput>();
        
        // 获取所有有指定资质的人员基础信息
        var qualifiedPersonnelList = await _personnelQualificationService.GetPersonnelIdsByQualificationIdsAsync(qualificationIds);

        var unavailablePersonnels = await _shiftUnavailabilityService.GetUnavailablePersonnelAsync(workStartTime, shiftId);
        
        // 检查每个有资质的人员是否在指定时间段内有意愿
        foreach (var personnel in qualifiedPersonnelList)
        {
            // 如果没有请假，则添加到可用人员列表
            if (!unavailablePersonnels.Any(p => p == personnel.Id))
            {
                // 获取人员资质信息
                var qualifications =
                    await _personnelQualificationService.GetActiveQualificationsByPersonnelIdAsync(personnel.Id);

                availablePersonnel.Add(new AvailablePersonnelOutput
                {
                    PersonnelId = personnel.Id,
                    PersonnelName = personnel.Name,
                    ShiftId = shiftId,
                    Qualifications = qualifications,
                });
            }
        }

        return availablePersonnel;
    }

    /// <summary>
    /// 检查人员是否具备指定资质
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <param name="qualificationId">资质ID</param>
    /// <returns></returns>
    public async Task<bool> HasQualificationAsync(long personnelId, long qualificationId)
    {
        var input = new PageInput<PersonnelQualificationGetPageInput>
        {
            Filter = new PersonnelQualificationGetPageInput 
            { 
                PersonnelId = personnelId,
                QualificationId = qualificationId,
                IsActive = true 
            },
            PageSize = 1,
            CurrentPage = 1
        };

        var result = await _personnelQualificationService.GetPageAsync(input);
        return result.Total > 0;
    }

    /// <summary>
    /// 获取所有人员池（用于智能分配）
    /// 深度业务思考：从资质表获取所有关联人员并去重，确保五层决策模型的完整性
    /// </summary>
    /// <param name="includeQualifications">是否包含资质信息</param>
    /// <returns>完整的人员池，用于后续的五层决策筛选</returns>
    public async Task<List<PersonnelPoolOutput>> GetAllPersonnelPoolAsync(bool includeQualifications = false)
    {
        try
        {
            // 从资质表获取所有有资质的人员ID，然后去重
            // 这确保了获取的人员池都是有资质记录的人员
            var allQualificationPersonnel = await _personnelQualificationService.GetAllPersonnelWithQualificationsAsync();
            
            if (allQualificationPersonnel == null || !allQualificationPersonnel.Any())
            {
                return new List<PersonnelPoolOutput>();
            }

            // 按人员ID去重分组，获取人员基础信息
            var groupedByPersonnel = allQualificationPersonnel
                .Where(pq => pq.PersonnelId > 0)
                .GroupBy(pq => pq.PersonnelId)
                .Select(g => g.First()) // 每个人员只取一条记录来获取基础信息
                .ToList();

            var personnelPoolOutputs = new List<PersonnelPoolOutput>();

            foreach (var qualificationRecord in groupedByPersonnel)
            {

                var poolOutput = new PersonnelPoolOutput
                {
                    Id = qualificationRecord.PersonnelId,
                    PersonnelName = qualificationRecord.PersonnelName,
                    IsActive = true,
                };

                // 如果需要包含资质信息
                if (includeQualifications)
                {
                    poolOutput.Qualifications =
                        await _personnelQualificationService.GetActiveQualificationsByPersonnelIdAsync(
                            qualificationRecord.PersonnelId);
                }

                personnelPoolOutputs.Add(poolOutput);

            }

            return personnelPoolOutputs.OrderBy(p => p.PersonnelCode).ToList();
        }
        catch (Exception ex)
        {
            return new List<PersonnelPoolOutput>();
        }
    }
}