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.Time;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Output;
using NPP.SmartSchedue.Api.Repositories.Time;
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;

namespace NPP.SmartSchedue.Api.Services.Time;

/// <summary>
/// 员工休假服务
/// </summary>
[DynamicApi(Area = "app")]
public class EmployeeLeaveService : BaseService, IEmployeeLeaveService, IDynamicApi
{
    private readonly EmployeeLeaveRepository _employeeLeaveRepository;

    public EmployeeLeaveService(EmployeeLeaveRepository employeeLeaveRepository)
    {
        _employeeLeaveRepository = employeeLeaveRepository;
    }

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

        return output;
    }

    /// <summary>
    /// 查询分页
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<PageOutput<EmployeeLeaveGetPageOutput>> GetPageAsync(PageInput<EmployeeLeaveGetPageInput> input)
    {
        var list = await _employeeLeaveRepository.Select
            .WhereIf(input.Filter?.EmployeeId.HasValue == true, a => a.EmployeeId == input.Filter.EmployeeId.Value)
            .WhereIf(!string.IsNullOrEmpty(input.Filter?.LeaveType), a => a.LeaveType.Contains(input.Filter.LeaveType))
            .WhereIf(!string.IsNullOrEmpty(input.Filter?.Status), a => a.Status.Contains(input.Filter.Status))
            .Count(out var total)
            .OrderByDescending(a => a.Id)
            .Page(input.CurrentPage, input.PageSize)
            .ToListAsync<EmployeeLeaveGetPageOutput>();

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

        return data;
    }

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

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

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

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

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

    /// <summary>
    /// 获取员工在指定时间段内的已批准请假记录
    /// </summary>
    /// <param name="employeeId">员工ID</param>
    /// <param name="startTime">开始时间</param>
    /// <param name="endTime">结束时间</param>
    /// <returns></returns>
    public async Task<List<EmployeeLeaveGetPageOutput>> GetApprovedLeavesByEmployeeAndTimeRangeAsync(
        long employeeId, 
        DateTime startTime, 
        DateTime endTime)
    {
        var leaves = await _employeeLeaveRepository.Select
            .Where(a => a.EmployeeId == employeeId)
            .Where(a => a.Status == "Approved") // 只查询已批准的请假
            .Where(a => a.StartTime <= endTime && a.EndTime >= startTime) // 时间段重叠判断
            .ToListAsync<EmployeeLeaveGetPageOutput>();

        return leaves;
    }

    /// <summary>
    /// 检查员工在指定时间段内是否有请假
    /// </summary>
    /// <param name="employeeId">员工ID</param>
    /// <param name="startTime">开始时间</param>
    /// <param name="endTime">结束时间</param>
    /// <returns></returns>
    public async Task<bool> HasApprovedLeaveInTimeRangeAsync(
        long employeeId, 
        DateTime startTime, 
        DateTime endTime)
    {
        var hasLeave = await _employeeLeaveRepository.Select
            .Where(a => a.EmployeeId == employeeId)
            .Where(a => a.Status == "Approved") // 只查询已批准的请假
            .Where(a => a.StartTime <= endTime && a.EndTime >= startTime) // 时间段重叠判断
            .AnyAsync();

        return hasLeave;
    }

    /// <summary>
    /// 检查员工在指定日期是否在请假
    /// 智能分配系统专用方法，返回详细的请假信息
    /// 深度业务思考：全面检查员工在指定日期的请假状态，支持多个重叠请假记录的场景
    /// </summary>
    /// <param name="employeeId">员工ID</param>
    /// <param name="checkDate">检查日期</param>
    /// <returns>请假状态信息</returns>
    public async Task<EmployeeLeaveStatusResult> IsOnLeaveAsync(long employeeId, DateTime checkDate)
    {
        try
        {
            // 将检查日期标准化为当天的日期范围（00:00:00 到 23:59:59）
            var checkDateStart = checkDate.Date;
            var checkDateEnd = checkDateStart.AddDays(1).AddTicks(-1);

            // 查询该员工在指定日期范围内所有已批准的请假记录
            var leaveRecords = await _employeeLeaveRepository.Select
                .Where(a => a.EmployeeId == employeeId)
                .Where(a => a.Status == "approved" || a.Status == "Approved") // 兼容不同的状态值格式
                .Where(a => a.StartTime <= checkDateEnd && a.EndTime >= checkDateStart) // 时间段重叠判断
                .OrderBy(a => a.StartTime)
                .ToListAsync();

            var result = new EmployeeLeaveStatusResult
            {
                CheckDate = checkDate,
                IsOnLeave = leaveRecords.Any(),
                LeaveRecords = new List<EmployeeLeaveInfo>()
            };

            if (!leaveRecords.Any())
            {
                // 没有请假记录
                return result;
            }

            // 转换请假记录到简化格式
            result.LeaveRecords = leaveRecords.Select(record => new EmployeeLeaveInfo
            {
                Id = record.Id,
                LeaveType = record.LeaveType,
                StartTime = record.StartTime,
                EndTime = record.EndTime,
                Reason = record.Reason
            }).ToList();

            // 设置主要请假信息（如果有多个重叠请假，取最早开始的一个作为主要信息）
            var primaryLeave = leaveRecords.First();
            result.LeaveType = primaryLeave.LeaveType;
            result.LeaveStartTime = primaryLeave.StartTime;
            result.LeaveEndTime = primaryLeave.EndTime;
            result.LeaveReason = primaryLeave.Reason;
            result.LeaveRecordId = primaryLeave.Id;

            return result;
        }
        catch (Exception ex)
        {
            // 异常情况下返回安全的默认结果
            return new EmployeeLeaveStatusResult
            {
                CheckDate = checkDate,
                IsOnLeave = false,
                LeaveRecords = new List<EmployeeLeaveInfo>(),
                LeaveReason = $"请假状态检查异常：{ex.Message}"
            };
        }
    }
} 