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.Repositories.Personnel;
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
using ZhonTai.Admin.Core.Consts;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using ZhonTai.Admin.Domain.User;

namespace NPP.SmartSchedue.Api.Services.Personnel;

/// <summary>
/// 人员资质绑定服务
/// </summary>
[DynamicApi(Area = "app")]
public class PersonnelQualificationService : BaseService, IPersonnelQualificationService, IDynamicApi
{
    private readonly PersonnelQualificationRepository _personnelQualificationRepository;
    private readonly QualificationRepository _qualificationRepository;

    public PersonnelQualificationService(
        PersonnelQualificationRepository personnelQualificationRepository,
        QualificationRepository qualificationRepository)
    {
        _personnelQualificationRepository = personnelQualificationRepository;
        _qualificationRepository = qualificationRepository;
    }

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

        return output;
    }

    /// <summary>
    /// 查询分页
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<PageOutput<PersonnelQualificationGetPageOutput>> GetPageAsync(PageInput<PersonnelQualificationGetPageInput> input)
    {
        var list = await _personnelQualificationRepository.Select
            .WhereIf(input.Filter?.PersonnelId.HasValue == true, a => a.PersonnelId == input.Filter.PersonnelId)
            .WhereIf(input.Filter?.QualificationId.HasValue == true, a => a.QualificationId == input.Filter.QualificationId)
            .WhereIf(input.Filter?.IsActive.HasValue == true, a => a.IsActive == input.Filter.IsActive)
            .Count(out var total)
            .OrderByDescending(a => a.Id)
            .Page(input.CurrentPage, input.PageSize)
            .ToListAsync<PersonnelQualificationGetPageOutput>();

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

        return data;
    }

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<long> AddAsync(PersonnelQualificationAddInput input)
    {
        var entity = Mapper.Map<PersonnelQualificationEntity>(input);
        var result = await _personnelQualificationRepository.InsertAsync(entity);
        return result.Id;
    }

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

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

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

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

    /// <summary>
    /// 根据资质ID列表获取具有这些资质的人员基础信息列表（ID + 姓名）
    /// </summary>
    /// <param name="qualificationIds">资质ID列表</param>
    /// <returns></returns>
    public async Task<List<PersonnelBasicInfo>> GetPersonnelIdsByQualificationIdsAsync(long[] qualificationIds)
    {
        var personnelInfoMap = new Dictionary<long, PersonnelBasicInfo>();
        
        var qualifiedPersonnel = await _personnelQualificationRepository.Select
            .Where(pq => qualificationIds.Contains(pq.QualificationId) && pq.IsActive)
            .ToListAsync(p => new PersonnelBasicInfo
            {
                Id = p.PersonnelId,
                Name = p.PersonnelName // 临时使用默认格式
            });

        // 去重处理
        foreach (var personnel in qualifiedPersonnel)
        {
            personnelInfoMap[personnel.Id] = personnel;
        }

        return personnelInfoMap.Values.ToList();
    }

    /// <summary>
    /// 根据资质ID字符串（逗号分隔）获取具有这些资质的人员基础信息列表（ID + 姓名）
    /// </summary>
    /// <param name="qualificationIds">资质ID字符串，使用逗号分隔</param>
    /// <returns></returns>
    public async Task<List<PersonnelBasicInfo>> GetPersonnelIdsByQualificationIdsAsync(string qualificationIds)
    {
        // 检查输入参数的有效性
        if (string.IsNullOrWhiteSpace(qualificationIds))
        {
            return new List<PersonnelBasicInfo>();
        }

        try
        {
            // 解析逗号分隔的字符串为long数组
            var qualificationIdArray = qualificationIds
                .Split(',', StringSplitOptions.RemoveEmptyEntries)
                .Select(id => id.Trim())
                .Where(id => !string.IsNullOrWhiteSpace(id))
                .Select(long.Parse)
                .ToArray();

            // 调用原有的数组版本方法
            return await GetPersonnelIdsByQualificationIdsAsync(qualificationIdArray);
        }
        catch (FormatException)
        {
            // 如果解析失败，返回空列表而不是抛出异常
            return new List<PersonnelBasicInfo>();
        }
        catch (OverflowException)
        {
            // 如果数值超出范围，返回空列表而不是抛出异常
            return new List<PersonnelBasicInfo>();
        }
    }

    /// <summary>
    /// 根据人员ID获取其所有有效资质信息
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <returns></returns>
    public async Task<List<PersonnelQualificationGetPageOutput>> GetActiveQualificationsByPersonnelIdAsync(long personnelId)
    {
        var input = new PageInput<PersonnelQualificationGetPageInput>
        {
            Filter = new PersonnelQualificationGetPageInput { PersonnelId = personnelId, IsActive = true },
            PageSize = 1000,
            CurrentPage = 1
        };

        var result = await GetPageAsync(input);
        return result.List?.ToList() ?? new List<PersonnelQualificationGetPageOutput>();
    }

    /// <summary>
    /// 获取所有有资质记录的人员列表（用于人员池构建）
    /// 深度业务思考：从资质表获取所有关联人员，确保智能分配系统的人员池完整性
    /// </summary>
    /// <returns>所有有资质记录的人员资质信息</returns>
    public async Task<List<PersonnelQualificationGetPageOutput>> GetAllPersonnelWithQualificationsAsync()
    {
        try
        {
            // 获取所有有效的人员资质记录
            // 这里不分页，获取全量数据用于构建人员池
            var entities = await _personnelQualificationRepository.Select
                .Where(pq => pq.PersonnelId > 0) // 确保有有效的人员ID
                .OrderBy(pq => pq.PersonnelId)
                .ToListAsync();

            // 手动映射确保PersonnelName字段被正确传递
            var results = entities.Select(entity => new PersonnelQualificationGetPageOutput
            {
                Id = entity.Id,
                PersonnelId = entity.PersonnelId,
                PersonnelName = entity.PersonnelName, // 【关键修复】确保人员姓名被正确映射
                QualificationId = entity.QualificationId,
                QualificationLevel = entity.QualificationLevel,
                ExpiryDate = entity.ExpiryDate,
                ExpiryWarningDays = entity.ExpiryWarningDays,
                RenewalDate = entity.RenewalDate,
                IsActive = entity.IsActive
            }).ToList();

            return results;
        }
        catch (Exception ex)
        {
            return new List<PersonnelQualificationGetPageOutput>();
        }
    }

    /// <summary>
    /// 根据人员ID获取其所有资质记录（包括无效的）
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <returns>人员的所有资质记录</returns>
    public async Task<List<PersonnelQualificationGetPageOutput>> GetByPersonnelIdAsync(long personnelId)
    {
        try
        {
            // 获取指定人员的所有资质记录，不论是否有效
            var entities = await _personnelQualificationRepository.Select
                .Where(pq => pq.PersonnelId == personnelId)
                .OrderBy(pq => pq.QualificationId)
                .ToListAsync();

            // 手动映射确保PersonnelName字段被正确传递
            var results = entities.Select(entity => new PersonnelQualificationGetPageOutput
            {
                Id = entity.Id,
                PersonnelId = entity.PersonnelId,
                PersonnelName = entity.PersonnelName, // 【关键修复】确保人员姓名被正确映射
                QualificationId = entity.QualificationId,
                QualificationLevel = entity.QualificationLevel,
                ExpiryDate = entity.ExpiryDate,
                ExpiryWarningDays = entity.ExpiryWarningDays,
                RenewalDate = entity.RenewalDate,
                IsActive = entity.IsActive
            }).ToList();

            return results;
        }
        catch (Exception ex)
        {
            return new List<PersonnelQualificationGetPageOutput>();
        }
    }

    /// <summary>
    /// 根据人员ID获取其所有有效的资质实体列表（用于智能分配系统资质匹配）
    /// 深度业务思考：智能分配系统需要完整的资质实体信息进行精确匹配计算
    /// 1. 只获取有效状态的资质记录（IsActive = true）
    /// 2. 检查资质有效期，排除已过期资质
    /// 3. 返回完整实体信息供复杂业务逻辑使用
    /// 4. 异常处理确保系统稳定性
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <returns>人员有效资质实体列表</returns>
    public async Task<List<PersonnelQualificationEntity>> GetPersonnelQualificationsAsync(long personnelId)
    {
        try
        {
            // 深度思考：智能分配系统需要精确的资质匹配
            // 必须同时满足：1. 状态有效 2. 未过期 3. 有效的人员关联
            var currentTime = DateTime.Now;
            
            var qualificationEntities = await _personnelQualificationRepository.Select
                .Where(pq => pq.PersonnelId == personnelId && 
                           pq.IsActive && // 必须是激活状态
                           (pq.ExpiryDate == null || pq.ExpiryDate > currentTime)) // 未过期或永久有效
                .OrderBy(pq => pq.QualificationId)
                .ToListAsync();

            return qualificationEntities ?? new List<PersonnelQualificationEntity>();
        }
        catch (Exception ex)
        {
            return new List<PersonnelQualificationEntity>();
        }
    }

    /// <summary>
    /// 获取人员资质统计信息（横坐标为资质，纵坐标为人员数量）
    /// </summary>
    /// <returns>人员资质统计结果</returns>
    public async Task<PersonnelQualificationStatisticsResult> GetPersonnelQualificationStatisticsAsync()
    {
        try
        {
            // 获取所有有效的人员资质记录
            var activeQualifications = await _personnelQualificationRepository.Select
                .Where(pq => pq.IsActive && (pq.ExpiryDate == null || pq.ExpiryDate > DateTime.Now))
                .ToListAsync(pq => new { pq.QualificationId, pq.PersonnelId });

            // 按资质ID分组并统计每个资质的人员数量
            var qualificationStatistics = activeQualifications
                .GroupBy(q => q.QualificationId)
                .Select(g => new
                {
                    QualificationId = g.Key,
                    PersonnelCount = g.Select(x => x.PersonnelId).Distinct().Count()
                })
                .ToList();

            // 获取所有资质的名称
            var qualificationIds = qualificationStatistics.Select(q => q.QualificationId).ToArray();
            var qualifications = await _qualificationRepository.Select
                .Where(q => qualificationIds.Contains(q.Id))
                .ToListAsync(q => new { q.Id, q.Name });

            var qualificationsDict = qualifications.ToDictionary(q => q.Id, q => q.Name);

            // 构建统计结果
            var statistics = qualificationStatistics
                .Select(stat => new PersonnelQualificationStatistics
                {
                    QualificationId = stat.QualificationId,
                    QualificationName = qualificationsDict.ContainsKey(stat.QualificationId) 
                        ? qualificationsDict[stat.QualificationId] 
                        : $"未知资质({stat.QualificationId})",
                    PersonnelCount = stat.PersonnelCount
                })
                .ToList();

            return new PersonnelQualificationStatisticsResult
            {
                Statistics = statistics,
                GeneratedTime = DateTime.Now
            };
        }
        catch (Exception ex)
        {
            // 发生异常时返回空的统计结果
            return new PersonnelQualificationStatisticsResult
            {
                Statistics = new List<PersonnelQualificationStatistics>(),
                GeneratedTime = DateTime.Now
            };
        }
    }

    /// <summary>
    /// 获取预警期内即将到期的人员资质清单
    /// </summary>
    /// <param name="today">基准日期（通常为 DateTime.Today）</param>
    /// <param name="personnelIds">限定人员范围（可选）</param>
    /// <param name="includeExpired">是否包含已过期记录</param>
    /// <returns></returns>
    public async Task<List<ExpiringQualificationItemOutput>> GetExpiringAsync(DateTime today, IList<long> personnelIds = null, bool includeExpired = false)
    {
        var baseDate = today.Date;

        var select = _personnelQualificationRepository.Select
            .Where(pq => pq.IsActive)
            .Where(pq => pq.ExpiryDate != null)
            .Where(pq => pq.ExpiryWarningDays != null && pq.ExpiryWarningDays > 0);

        if (personnelIds != null && personnelIds.Count > 0)
        {
            select = select.Where(pq => personnelIds.Contains(pq.PersonnelId));
        }

        var list = await select.ToListAsync();

        // 批量查询资质名称，避免 N+1
        var qIds = list.Select(x => x.QualificationId).Distinct().ToArray();
        var qNameMap = qIds.Length == 0
            ? new Dictionary<long, string>()
            : (await _qualificationRepository.Select
                    .Where(q => qIds.Contains(q.Id))
                    .ToListAsync(q => new { q.Id, q.Name }))
                .ToDictionary(x => x.Id, x => x.Name ?? string.Empty);

        var result = new List<ExpiringQualificationItemOutput>(list.Count);
        foreach (var it in list)
        {
            var expiry = it.ExpiryDate.Value.Date;
            var daysLeft = (int)Math.Floor((expiry - baseDate).TotalDays);

            bool inWindow = includeExpired
                ? daysLeft <= it.ExpiryWarningDays.Value
                : daysLeft >= 0 && daysLeft <= it.ExpiryWarningDays.Value;

            if (!inWindow) continue;

            result.Add(new ExpiringQualificationItemOutput
            {
                PersonnelId = it.PersonnelId,
                PersonnelName = it.PersonnelName,
                PersonnelCode = it.PersonnelCode,
                QualificationId = it.QualificationId,
                QualificationLevel = it.QualificationLevel,
                ExpiryDate = it.ExpiryDate,
                DaysLeft = daysLeft,
                QualificationName = qNameMap.TryGetValue(it.QualificationId, out var qn) ? qn : string.Empty
            });
        }

        return result
            .OrderBy(x => x.DaysLeft)
            .ThenBy(x => x.ExpiryDate)
            .ToList();
    }
} 