using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Time.Output;
using ZhonTai.Admin.Core.Dto;

namespace NPP.SmartSchedue.Api.Contracts.Services.Time;

/// <summary>
/// 班次不可用标记服务接口
/// 提供班次不可用数据的业务逻辑处理
/// </summary>
public interface IShiftUnavailabilityService
{
    #region 基础CRUD操作
    
    /// <summary>
    /// 添加班次不可用标记
    /// </summary>
    /// <param name="input">添加输入模型</param>
    /// <returns>新创建记录的ID</returns>
    Task<long> AddAsync(ShiftUnavailabilityAddInput input);
    
    /// <summary>
    /// 更新班次不可用标记
    /// </summary>
    /// <param name="input">更新输入模型</param>
    /// <returns>是否更新成功</returns>
    Task<bool> UpdateAsync(ShiftUnavailabilityUpdateInput input);
    
    /// <summary>
    /// 删除班次不可用标记
    /// </summary>
    /// <param name="id">记录ID</param>
    /// <returns>是否删除成功</returns>
    Task<bool> DeleteAsync(long id);
    
    /// <summary>
    /// 获取班次不可用标记详情
    /// </summary>
    /// <param name="id">记录ID</param>
    /// <returns>详情信息</returns>
    Task<ShiftUnavailabilityGetOutput> GetAsync(long id);
    
    /// <summary>
    /// 分页查询班次不可用标记
    /// </summary>
    /// <param name="input">查询条件</param>
    /// <returns>分页结果</returns>
    Task<PageOutput<ShiftUnavailabilityGetPageOutput>> GetPageAsync(PageInput<ShiftUnavailabilityGetPageInput> input);
    
    #endregion

    #region 网格视图专用方法
    
    /// <summary>
    /// 获取指定员工指定月份的网格数据
    /// 用于前端网格组件的数据加载
    /// </summary>
    /// <param name="personnelId">员工ID</param>
    /// <param name="month">月份</param>
    /// <returns>网格数据</returns>
    Task<GridDataOutput> GetMonthlyGridDataAsync(long personnelId, DateTime month);
    
    /// <summary>
    /// 切换单元格状态（快速操作）
    /// 如果该单元格已标记为不可用，则清除；否则用默认原因标记为不可用
    /// </summary>
    /// <param name="input">切换输入</param>
    /// <returns>操作结果</returns>
    Task<bool> ToggleCellAsync(CellToggleInput input);
    
    /// <summary>
    /// 设置单元格状态（精确操作）
    /// </summary>
    /// <param name="input">设置输入</param>
    /// <returns>操作结果</returns>
    Task<bool> SetCellAsync(CellSetInput input);
    
    #endregion

    #region 批量操作方法
    
    /// <summary>
    /// 模板复制
    /// 将指定日期的班次不可用设置复制到其他日期
    /// </summary>
    /// <param name="input">复制输入</param>
    /// <returns>批量操作结果</returns>
    Task<BatchOperationResult> CopyTemplateAsync(TemplateCopyInput input);
    
    /// <summary>
    /// 周期性设置
    /// 按周模式批量设置班次不可用标记
    /// </summary>
    /// <param name="input">周期设置输入</param>
    /// <returns>批量操作结果</returns>
    Task<BatchOperationResult> SetWeeklyPatternAsync(WeeklyPatternInput input);
    
    /// <summary>
    /// 批量设置单元格
    /// </summary>
    /// <param name="input">批量设置输入</param>
    /// <returns>批量操作结果</returns>
    Task<BatchOperationResult> BatchSetCellsAsync(BatchCellEditInput input);
    
    #endregion

    #region 智能排班集成方法
    
    /// <summary>
    /// 获取指定日期和班次的不可用员工ID列表
    /// 用于智能排班算法过滤不可用人员
    /// </summary>
    /// <param name="date">日期</param>
    /// <param name="shiftId">班次ID</param>
    /// <returns>不可用员工ID列表</returns>
    Task<List<long>> GetUnavailablePersonnelAsync(DateTime date, long shiftId);

    /// <summary>
    /// 检查人员班次的意愿
    /// </summary>
    /// <param name="date"></param>
    /// <param name="shiftId"></param>
    /// <param name="personnelId"></param>
    /// <returns></returns>
    Task<bool> CheckUnavailablePersonnelByShift(DateTime date, long shiftId, long personnelId);
    
    /// <summary>
    /// 获取指定日期所有班次的不可用员工分布
    /// </summary>
    /// <param name="date">日期</param>
    /// <returns>班次ID -> 不可用员工ID列表的字典</returns>
    Task<Dictionary<long, List<long>>> GetDailyUnavailablePersonnelAsync(DateTime date);
    
    /// <summary>
    /// 批量获取日期范围内的不可用员工分布
    /// 用于智能排班算法的批量优化查询
    /// </summary>
    /// <param name="startDate">开始日期</param>
    /// <param name="endDate">结束日期</param>
    /// <returns>日期 -> (班次ID -> 不可用员工ID列表) 的嵌套字典</returns>
    Task<Dictionary<DateTime, Dictionary<long, List<long>>>> GetRangeUnavailablePersonnelAsync(DateTime startDate, DateTime endDate);
    
    #endregion

    #region 统计分析方法
    
    /// <summary>
    /// 获取员工不可用统计信息
    /// </summary>
    /// <param name="personnelId">员工ID</param>
    /// <param name="startDate">开始日期</param>
    /// <param name="endDate">结束日期</param>
    /// <returns>统计信息</returns>
    Task<UnavailabilityStatistics> GetStatisticsAsync(long personnelId, DateTime startDate, DateTime endDate);
    
    /// <summary>
    /// 获取团队不可用报表
    /// </summary>
    /// <param name="personnelIds">员工ID列表</param>
    /// <param name="month">月份</param>
    /// <returns>团队报表列表</returns>
    Task<List<UnavailabilityStatistics>> GetTeamReportAsync(List<long> personnelIds, DateTime month);
    
    #endregion
}