using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Mapster;
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
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.Contracts.Core.Enums;
using NPP.SmartSchedue.Api.Contracts.Core.Extensions;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using Microsoft.AspNetCore.Mvc;
using NPP.SmartSchedue.Api.Contracts;

namespace NPP.SmartSchedue.Api.Services.Time;

/// <summary>
/// 班次不可用标记服务实现
/// 提供班次不可用数据的完整业务逻辑处理
/// </summary>
[DynamicApi(Area = "app")]
public class ShiftUnavailabilityService : BaseService, IShiftUnavailabilityService, IDynamicApi
{
    private readonly IShiftUnavailabilityRepository _repository;
    private readonly IShiftRepository _shiftRepository;

    public ShiftUnavailabilityService(
        IShiftUnavailabilityRepository repository,
        IShiftRepository shiftRepository)
    {
        _repository = repository;
        _shiftRepository = shiftRepository;
    }

    #region 基础CRUD操作

    /// <summary>
    /// 添加班次不可用标记
    /// </summary>
    public async Task<long> AddAsync(ShiftUnavailabilityAddInput input)
    {
        // 检查是否已存在相同的记录
        var exists = await _repository.ExistsAsync(input.PersonnelId, input.Date, input.ShiftId);
        if (exists)
        {
            throw new Exception($"员工在 {input.Date:yyyy-MM-dd} 的该班次已有不可用标记");
        }

        var entity = input.Adapt<ShiftUnavailabilityEntity>();
        entity.ReasonType = (int)input.ReasonType;
        entity.CreatedTime = DateTime.Now;

        await _repository.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 更新班次不可用标记
    /// </summary>
    public async Task<bool> UpdateAsync(ShiftUnavailabilityUpdateInput input)
    {
        var entity = await _repository.GetAsync(input.Id);
        if (entity == null)
        {
            throw new Exception("记录不存在");
        }

        // 更新可修改的字段
        entity.ReasonType = (int)input.ReasonType;
        entity.Remark = input.Remark;
        entity.Priority = input.Priority;
        entity.EffectiveStartTime = input.EffectiveStartTime;
        entity.EffectiveEndTime = input.EffectiveEndTime;
        entity.ModifiedTime = DateTime.Now;

        return await _repository.UpdateAsync(entity) > 0;
    }

    /// <summary>
    /// 删除班次不可用标记
    /// </summary>
    public async Task<bool> DeleteAsync(long id)
    {
        return await _repository.DeleteAsync(id) > 0;
    }

    /// <summary>
    /// 获取班次不可用标记详情
    /// </summary>
    public async Task<ShiftUnavailabilityGetOutput> GetAsync(long id)
    {
        var entity = await _repository.GetAsync(id);
        if (entity == null) return null;

        var output = entity.Adapt<ShiftUnavailabilityGetOutput>();
        
        // 设置枚举和扩展属性
        output.ReasonType = ((UnavailabilityReasonType)entity.ReasonType);
        output.ReasonTypeName = entity.ReasonType.GetDisplayName();
        output.Category = entity.ReasonType.GetCategory();
        output.CategoryName = output.Category.ToString();
        output.GridSymbol = entity.ReasonType.GetGridSymbol();
        output.ColorClass = entity.ReasonType.GetColorClass();

        return output;
    }

    /// <summary>
    /// 分页查询班次不可用标记
    /// </summary>
    public async Task<PageOutput<ShiftUnavailabilityGetPageOutput>> GetPageAsync(PageInput<ShiftUnavailabilityGetPageInput>  input)
    {
        var query = _repository.Select;

        // 条件过滤
        if (input.Filter.PersonnelId.HasValue)
            query = query.Where(x => x.PersonnelId == input.Filter.PersonnelId.Value);

        if (input.Filter.ShiftId.HasValue)
            query = query.Where(x => x.ShiftId == input.Filter.ShiftId.Value);

        if (input.Filter.StartDate.HasValue)
            query = query.Where(x => x.Date >= input.Filter.StartDate.Value.Date);

        if (input.Filter.EndDate.HasValue)
            query = query.Where(x => x.Date <= input.Filter.EndDate.Value.Date);

        if (input.Filter.ReasonType.HasValue)
            query = query.Where(x => x.ReasonType == (int)input.Filter.ReasonType.Value);

        if (input.Filter.Category.HasValue)
        {
            // 根据分组筛选对应的原因类型
            var reasonTypes = GetReasonTypesByCategory(input.Filter.Category.Value);
            query = query.Where(x => reasonTypes.Contains(x.ReasonType));
        }

        if (input.Filter.IsFromTemplate.HasValue)
            query = query.Where(x => x.IsFromTemplate == input.Filter.IsFromTemplate.Value);

        if (!string.IsNullOrWhiteSpace(input.Filter.Keyword))
            query = query.Where(x => x.Remark.Contains(input.Filter.Keyword));

        // 使用标准的FreeSql分页方式
        var entities = await query
            .Count(out var total)
            .OrderByDescending(x => x.CreatedTime)
            .Page(input.CurrentPage, input.PageSize)
            .ToListAsync();

        // 手动进行数据转换
        var list = entities.Select(entity =>
        {
            var output = entity.Adapt<ShiftUnavailabilityGetPageOutput>();
            
            // 设置扩展属性
            output.ReasonType = (UnavailabilityReasonType)entity.ReasonType;
            output.ReasonTypeName = entity.ReasonType.GetDisplayName();
            output.Category = entity.ReasonType.GetCategory();
            output.GridSymbol = entity.ReasonType.GetGridSymbol();
            output.ColorClass = entity.ReasonType.GetColorClass();
            output.DateDisplay = entity.Date.ToString("yyyy-MM-dd");
            output.Weekday = GetWeekdayName(entity.Date);
            
            if (entity.SourceTemplateDate.HasValue)
                output.SourceTemplateDateDisplay = entity.SourceTemplateDate.Value.ToString("yyyy-MM-dd");

            return output;
        }).ToList();

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

        return data;
    }

    #endregion

    #region 网格视图专用方法

    /// <summary>
    /// 获取指定员工指定月份的网格数据
    /// </summary>
    public async Task<GridDataOutput> GetMonthlyGridDataAsync(long personnelId, DateTime month)
    {
        var monthStart = new DateTime(month.Year, month.Month, 1);
        var monthEnd = monthStart.AddMonths(1).AddDays(-1);

        // 一次性查询整月数据
        var entities = await _repository.GetByPersonnelAndDateRangeAsync(personnelId, monthStart, monthEnd);
        
        // 获取所有启用的班次
        var shifts = await _shiftRepository.Select
            .Where(x => x.IsEnabled)
            .ToListAsync();
        
        // 构建网格数据结构
        var grid = new Dictionary<DateTime, Dictionary<long, CellData>>();
        var dates = new List<DateTime>();
        
        // 初始化所有日期和班次的空单元格
        for (var date = monthStart; date <= monthEnd; date = date.AddDays(1))
        {
            dates.Add(date);
            grid[date] = new Dictionary<long, CellData>();
            
            foreach (var shift in shifts)
            {
                grid[date][shift.Id] = new CellData
                {
                    IsUnavailable = false,
                    DisplaySymbol = "",
                    CssClass = "",
                    TooltipText = $"{shift.Name} - 可用"
                };
            }
        }

        // 填充不可用数据
        foreach (var entity in entities)
        {
            if (grid.ContainsKey(entity.Date.Date) && grid[entity.Date.Date].ContainsKey(entity.ShiftId))
            {
                var reasonType = (UnavailabilityReasonType)entity.ReasonType;
                grid[entity.Date.Date][entity.ShiftId] = new CellData
                {
                    IsUnavailable = true,
                    ReasonType = reasonType,
                    DisplaySymbol = entity.ReasonType.GetGridSymbol(),
                    CssClass = entity.ReasonType.GetColorClass(),
                    Remark = entity.Remark,
                    Priority = entity.Priority,
                    IsFromTemplate = entity.IsFromTemplate,
                    RecordId = entity.Id,
                    TooltipText = $"{entity.ReasonType.GetDisplayName()}: {entity.Remark}"
                };
            }
        }

        // 构建统计信息
        var statistics = BuildGridStatistics(entities, shifts);

        return new GridDataOutput
        {
            Grid = grid,
            Dates = dates,
            Shifts = shifts.Select(s => new ShiftInfo
            {
                Id = s.Id,
                Name = s.Name,
                ShiftNumber = s.ShiftNumber,
                StartTime = s.StartTime,
                EndTime = s.EndTime,
                TimeRange = $"{s.StartTime:hh\\:mm}-{s.EndTime:hh\\:mm}",
                IsEnabled = s.IsEnabled
            }).ToList(),
            Statistics = statistics,
            MonthDisplay = month.ToString("yyyy年MM月")
        };
    }

    /// <summary>
    /// 切换单元格状态
    /// </summary>
    public async Task<bool> ToggleCellAsync(CellToggleInput input)
    {
        var exists = await _repository.ExistsAsync(input.PersonnelId, input.Date, input.ShiftId);
        
        if (exists)
        {
            // 删除现有记录
            return await _repository.DeleteByConditionAsync(input.PersonnelId, input.Date, input.ShiftId) > 0;
        }
        else
        {
            // 创建新记录，使用默认的个人意愿原因
            var entity = new ShiftUnavailabilityEntity
            {
                PersonnelId = input.PersonnelId,
                Date = input.Date,
                ShiftId = input.ShiftId,
                ReasonType = (int)UnavailabilityReasonType.PersonalPreference,
                Priority = 1,
                CreatedTime = DateTime.Now
            };

            await _repository.InsertAsync(entity);
            return true;
        }
    }

    /// <summary>
    /// 设置单元格状态
    /// </summary>
    public async Task<bool> SetCellAsync(CellSetInput input)
    {
        // 先删除现有记录
        await _repository.DeleteByConditionAsync(input.PersonnelId, input.Date, input.ShiftId);

        // 如果指定了原因类型，则创建新记录
        if (input.ReasonType.HasValue)
        {
            var entity = new ShiftUnavailabilityEntity
            {
                PersonnelId = input.PersonnelId,
                Date = input.Date,
                ShiftId = input.ShiftId,
                ReasonType = (int)input.ReasonType.Value,
                Remark = input.Remark,
                Priority = input.Priority,
                CreatedTime = DateTime.Now
            };

            await _repository.InsertAsync(entity);
        }

        return true;
    }

    #endregion

    #region 智能排班集成方法

    /// <summary>
    /// 获取指定日期和班次的不可用员工ID列表
    /// </summary>
    public async Task<List<long>> GetUnavailablePersonnelAsync(DateTime date, long shiftId)
    {
        return await _repository.GetUnavailablePersonnelIdsAsync(date, shiftId);
    }

    /// <summary>
    /// 检查人员班次的意愿
    /// </summary>
    /// <param name="date"></param>
    /// <param name="shiftId"></param>
    /// <param name="personnelId"></param>
    /// <returns></returns>
    public async Task<bool> CheckUnavailablePersonnelByShift(DateTime date, long shiftId, long personnelId)
    {
        return await _repository.CheckUnavailablePersonnelByShiftAsync(date, shiftId, personnelId);
    }

    /// <summary>
    /// 获取指定日期所有班次的不可用员工分布
    /// </summary>
    public async Task<Dictionary<long, List<long>>> GetDailyUnavailablePersonnelAsync(DateTime date)
    {
        return await _repository.GetDailyUnavailablePersonnelAsync(date);
    }

    /// <summary>
    /// 批量获取日期范围内的不可用员工分布
    /// </summary>
    public async Task<Dictionary<DateTime, Dictionary<long, List<long>>>> GetRangeUnavailablePersonnelAsync(DateTime startDate, DateTime endDate)
    {
        return await _repository.GetRangeUnavailablePersonnelAsync(startDate, endDate);
    }

    #endregion

    #region 私有辅助方法

    /// <summary>
    /// 根据分组获取对应的原因类型列表
    /// </summary>
    private static List<int> GetReasonTypesByCategory(UnavailabilityCategory category)
    {
        var allReasonTypes = Enum.GetValues<UnavailabilityReasonType>();
        return allReasonTypes
            .Where(rt => rt.GetCategory() == category)
            .Select(rt => (int)rt)
            .ToList();
    }

    /// <summary>
    /// 获取星期几的中文名称
    /// </summary>
    private static string GetWeekdayName(DateTime date)
    {
        return date.DayOfWeek switch
        {
            DayOfWeek.Sunday => "周日",
            DayOfWeek.Monday => "周一",
            DayOfWeek.Tuesday => "周二",
            DayOfWeek.Wednesday => "周三",
            DayOfWeek.Thursday => "周四",
            DayOfWeek.Friday => "周五",
            DayOfWeek.Saturday => "周六",
            _ => ""
        };
    }

    /// <summary>
    /// 构建网格统计信息
    /// </summary>
    private static GridStatistics BuildGridStatistics(List<ShiftUnavailabilityEntity> entities, List<ShiftEntity> shifts)
    {
        var stats = new GridStatistics
        {
            TotalCount = entities.Count,
            TemplateGeneratedCount = entities.Count(e => e.IsFromTemplate),
            ManualCreatedCount = entities.Count(e => !e.IsFromTemplate)
        };

        // 按班次统计
        stats.ShiftCounts = entities
            .GroupBy(e => e.ShiftId)
            .ToDictionary(g => g.Key, g => g.Count());

        // 按原因类型统计
        stats.ReasonTypeCounts = entities
            .GroupBy(e => (UnavailabilityReasonType)e.ReasonType)
            .ToDictionary(g => g.Key, g => g.Count());

        // 按分组统计
        stats.CategoryCounts = entities
            .GroupBy(e => ((UnavailabilityReasonType)e.ReasonType).GetCategory())
            .ToDictionary(g => g.Key, g => g.Count());

        return stats;
    }

    #endregion

    // 注意：批量操作方法和统计方法由于篇幅限制，将在后续实现
    // 这里先提供基础CRUD和核心功能的完整实现

    #region 待实现的方法（Phase 2 将完成）

    /// <summary>
    /// 复制模板到指定日期范围
    /// 支持覆盖模式和保留模式
    /// </summary>
    public async Task<BatchOperationResult> CopyTemplateAsync(TemplateCopyInput input)
    {
        var result = new BatchOperationResult
        {
            TotalCount = 0,
            SuccessCount = 0,
            FailedCount = 0,
            FailedItems = new List<BatchOperationFailedItem>()
        };

        try
        {
            // 获取模板日期的所有记录
            var templateRecords = await _repository.GetByPersonnelAndDateRangeAsync(
                input.PersonnelId, input.SourceDate.Date, input.SourceDate.Date);

            if (!templateRecords.Any())
            {
                result.Message = "模板日期没有找到任何不可用记录";
                return result;
            }

            // 准备目标日期列表
            var targetDates = input.TargetDates.Select(d => d.Date).ToList();

            result.TotalCount = targetDates.Count * templateRecords.Count;

            // 使用事务确保数据一致性
            using var uow = _repository.Orm.CreateUnitOfWork();
            try
            {
                foreach (var targetDate in targetDates)
                {
                    // 如果是覆盖模式，先删除目标日期的现有记录
                    if (input.OverwriteExisting)
                    {
                        await _repository.DeleteByConditionAsync(input.PersonnelId, targetDate, null);
                    }

                    // 复制每条模板记录到目标日期
                    foreach (var templateRecord in templateRecords)
                    {
                        try
                        {
                            // 检查是否已存在相同记录
                            var exists = await _repository.ExistsAsync(input.PersonnelId, targetDate, templateRecord.ShiftId);
                            
                            if (!exists || input.OverwriteExisting)
                            {
                                // 创建新记录
                                var newRecord = new ShiftUnavailabilityEntity
                                {
                                    PersonnelId = input.PersonnelId,
                                    Date = targetDate,
                                    ShiftId = templateRecord.ShiftId,
                                    ReasonType = templateRecord.ReasonType,
                                    Remark = $"{templateRecord.Remark} (从{input.SourceDate:yyyy-MM-dd}复制)",
                                    Priority = templateRecord.Priority,
                                    EffectiveStartTime = templateRecord.EffectiveStartTime,
                                    EffectiveEndTime = templateRecord.EffectiveEndTime,
                                    IsFromTemplate = true,
                                    SourceTemplateDate = input.SourceDate.Date,
                                    CreatedTime = DateTime.Now
                                };

                                if (exists && input.OverwriteExisting)
                                {
                                    // 更新现有记录
                                    await _repository.DeleteByConditionAsync(input.PersonnelId, targetDate, templateRecord.ShiftId);
                                }

                                await _repository.InsertAsync(newRecord);
                                result.SuccessCount++;
                            }
                            else
                            {
                                // 记录已存在且不是覆盖模式
                                result.FailedCount++;
                                result.FailedItems.Add(new BatchOperationFailedItem
                                {
                                    Date = targetDate,
                                    ShiftId = templateRecord.ShiftId,
                                    Reason = "记录已存在"
                                });
                            }
                        }
                        catch (Exception ex)
                        {
                            result.FailedCount++;
                            result.FailedItems.Add(new BatchOperationFailedItem
                            {
                                Date = targetDate,
                                ShiftId = templateRecord.ShiftId,
                                Reason = $"操作失败: {ex.Message}"
                            });
                        }
                    }
                }

                uow.Commit();
                result.IsSuccess = result.FailedCount == 0;
                result.Message = result.IsSuccess ? 
                    $"模板复制成功，共处理 {result.SuccessCount} 条记录" : 
                    $"模板复制完成，成功 {result.SuccessCount} 条，失败 {result.FailedCount} 条";
            }
            catch (Exception)
            {
                uow.Rollback();
                throw;
            }
        }
        catch (Exception ex)
        {
            result.IsSuccess = false;
            result.Message = $"模板复制操作失败: {ex.Message}";
            result.FailedCount = result.TotalCount;
        }

        return result;
    }

    /// <summary>
    /// 设置周期性模式
    /// 根据周模式在指定日期范围内批量生成记录
    /// </summary>
    public async Task<BatchOperationResult> SetWeeklyPatternAsync(WeeklyPatternInput input)
    {
        var result = new BatchOperationResult
        {
            TotalCount = 0,
            SuccessCount = 0,
            FailedCount = 0,
            FailedItems = new List<BatchOperationFailedItem>()
        };

        try
        {
            // 验证输入参数
            if (input.WeeklyPattern?.Any() != true)
            {
                result.Message = "周模式配置不能为空";
                return result;
            }

            if (input.StartDate > input.EndDate)
            {
                result.Message = "开始日期不能大于结束日期";
                return result;
            }

            var processedDates = new List<DateTime>();
            
            // 遍历日期范围内的所有日期
            for (var date = input.StartDate.Date; 
                 date <= input.EndDate.Date; 
                 date = date.AddDays(1))
            {
                var dayOfWeek = (int)date.DayOfWeek;
                
                // 检查当前星期几是否在周模式配置中
                if (input.WeeklyPattern.ContainsKey(dayOfWeek) && input.WeeklyPattern[dayOfWeek]?.Any() == true)
                {
                    processedDates.Add(date);
                    result.TotalCount += input.WeeklyPattern[dayOfWeek].Count;
                }
            }

            if (result.TotalCount == 0)
            {
                result.Message = "根据周模式配置，没有需要处理的日期";
                return result;
            }

            // 使用事务确保数据一致性
            using var uow = _repository.Orm.CreateUnitOfWork();
            try
            {
                foreach (var date in processedDates)
                {
                    var dayOfWeek = (int)date.DayOfWeek;
                    var shiftIds = input.WeeklyPattern[dayOfWeek];

                    // 如果是覆盖模式，先删除该日期的现有记录
                    if (input.OverwriteExisting)
                    {
                        await _repository.DeleteByConditionAsync(input.PersonnelId, date, null);
                    }

                    // 为每个班次设置创建记录
                    foreach (var shiftId in shiftIds)
                    {
                        try
                        {
                            // 检查是否已存在记录
                            var exists = await _repository.ExistsAsync(input.PersonnelId, date, shiftId);
                            
                            if (!exists || input.OverwriteExisting)
                            {
                                var newRecord = new ShiftUnavailabilityEntity
                                {
                                    PersonnelId = input.PersonnelId,
                                    Date = date,
                                    ShiftId = shiftId,
                                    ReasonType = (int)input.ReasonType,
                                    Remark = $"{input.Remark ?? "周期性设置"} ({GetWeekdayName(date)})",
                                    Priority = input.Priority,
                                    IsFromTemplate = true,
                                    SourceTemplateDate = input.StartDate,
                                    CreatedTime = DateTime.Now
                                };

                                if (exists && input.OverwriteExisting)
                                {
                                    await _repository.DeleteByConditionAsync(input.PersonnelId, date, shiftId);
                                }

                                await _repository.InsertAsync(newRecord);
                                result.SuccessCount++;
                            }
                            else
                            {
                                // 记录已存在且不是覆盖模式
                                result.FailedCount++;
                                result.FailedItems.Add(new BatchOperationFailedItem
                                {
                                    Date = date,
                                    ShiftId = shiftId,
                                    Reason = "记录已存在"
                                });
                            }
                        }
                        catch (Exception ex)
                        {
                            result.FailedCount++;
                            result.FailedItems.Add(new BatchOperationFailedItem
                            {
                                Date = date,
                                ShiftId = shiftId,
                                Reason = $"操作失败: {ex.Message}"
                            });
                        }
                    }
                }

                uow.Commit();
                result.IsSuccess = result.FailedCount == 0;
                result.Message = result.IsSuccess ? 
                    $"周期性设置成功，共处理 {result.SuccessCount} 条记录，涉及 {processedDates.Count} 个日期" : 
                    $"周期性设置完成，成功 {result.SuccessCount} 条，失败 {result.FailedCount} 条";
            }
            catch (Exception)
            {
                uow.Rollback();
                throw;
            }
        }
        catch (Exception ex)
        {
            result.IsSuccess = false;
            result.Message = $"周期性设置操作失败: {ex.Message}";
            result.FailedCount = result.TotalCount;
        }

        return result;
    }

    /// <summary>
    /// 批量设置单元格状态
    /// 支持多选单元格的批量操作
    /// </summary>
    public async Task<BatchOperationResult> BatchSetCellsAsync(BatchCellEditInput input)
    {
        var result = new BatchOperationResult
        {
            TotalCount = 0,
            SuccessCount = 0,
            FailedCount = 0,
            FailedItems = new List<BatchOperationFailedItem>()
        };

        try
        {
            // 验证输入参数
            if (input.CellOperations?.Any() != true)
            {
                result.Message = "单元格操作列表不能为空";
                return result;
            }

            result.TotalCount = input.CellOperations.Count;

            // 使用事务确保数据一致性
            using var uow = _repository.Orm.CreateUnitOfWork();
            
            try
            {
                foreach (var operation in input.CellOperations)
                {
                    try
                    {
                        switch (operation.Operation)
                        {
                            case BatchCellOperationType.Set:
                                await HandleSetOperationAsync(operation, input.MarkAsTemplate, input.Remark);
                                break;
                            
                            case BatchCellOperationType.Clear:
                                await HandleClearOperationAsync(operation);
                                break;
                            
                            case BatchCellOperationType.Toggle:
                                await HandleToggleOperationAsync(operation);
                                break;
                            
                            default:
                                throw new ArgumentException($"不支持的操作类型: {operation.Operation}");
                        }
                        
                        result.SuccessCount++;
                    }
                    catch (Exception ex)
                    {
                        result.FailedCount++;
                        result.FailedItems.Add(new BatchOperationFailedItem
                        {
                            Date = operation.Date,
                            ShiftId = operation.ShiftId,
                            Reason = $"操作失败: {ex.Message}"
                        });
                    }
                }

                uow.Commit();
                result.IsSuccess = result.FailedCount == 0;
                result.Message = result.IsSuccess ? 
                    $"批量设置成功，共处理 {result.SuccessCount} 个单元格" : 
                    $"批量设置完成，成功 {result.SuccessCount} 个，失败 {result.FailedCount} 个";
            }
            catch (Exception)
            {
                uow.Rollback();
                throw;
            }
        }
        catch (Exception ex)
        {
            result.IsSuccess = false;
            result.Message = $"批量单元格设置操作失败: {ex.Message}";
            result.FailedCount = result.TotalCount;
        }

        return result;
    }

    /// <summary>
    /// 处理设置操作
    /// </summary>
    private async Task HandleSetOperationAsync(BatchCellOperation operation, bool markAsTemplate, string batchRemark)
    {
        if (!operation.ReasonType.HasValue)
        {
            throw new ArgumentException("Set操作必须指定原因类型");
        }

        // 先删除现有记录
        await _repository.DeleteByConditionAsync(operation.PersonnelId, operation.Date, operation.ShiftId);

        // 创建新记录
        var newRecord = new ShiftUnavailabilityEntity
        {
            PersonnelId = operation.PersonnelId,
            Date = operation.Date,
            ShiftId = operation.ShiftId,
            ReasonType = (int)operation.ReasonType.Value,
            Remark = operation.Remark ?? batchRemark ?? "批量设置",
            Priority = operation.Priority ?? 1,
            EffectiveStartTime = operation.EffectiveStartTime.HasValue ? TimeSpan.FromTicks(operation.EffectiveStartTime.Value.Ticks) : null,
            EffectiveEndTime = operation.EffectiveEndTime.HasValue ? TimeSpan.FromTicks(operation.EffectiveEndTime.Value.Ticks) : null,
            IsFromTemplate = markAsTemplate,
            SourceTemplateDate = markAsTemplate ? DateTime.Today : null,
            CreatedTime = DateTime.Now
        };

        await _repository.InsertAsync(newRecord);
    }

    /// <summary>
    /// 处理清除操作
    /// </summary>
    private async Task HandleClearOperationAsync(BatchCellOperation operation)
    {
        await _repository.DeleteByConditionAsync(operation.PersonnelId, operation.Date, operation.ShiftId);
    }

    /// <summary>
    /// 处理切换操作
    /// </summary>
    private async Task HandleToggleOperationAsync(BatchCellOperation operation)
    {
        var exists = await _repository.ExistsAsync(operation.PersonnelId, operation.Date, operation.ShiftId);
        
        if (exists)
        {
            // 删除现有记录
            await _repository.DeleteByConditionAsync(operation.PersonnelId, operation.Date, operation.ShiftId);
        }
        else
        {
            // 创建新记录，使用个人意愿作为默认原因
            var newRecord = new ShiftUnavailabilityEntity
            {
                PersonnelId = operation.PersonnelId,
                Date = operation.Date,
                ShiftId = operation.ShiftId,
                ReasonType = (int)UnavailabilityReasonType.PersonalPreference,
                Remark = operation.Remark ?? "切换操作",
                Priority = operation.Priority ?? 1,
                EffectiveStartTime = operation.EffectiveStartTime.HasValue ? TimeSpan.FromTicks(operation.EffectiveStartTime.Value.Ticks) : null,
                EffectiveEndTime = operation.EffectiveEndTime.HasValue ? TimeSpan.FromTicks(operation.EffectiveEndTime.Value.Ticks) : null,
                CreatedTime = DateTime.Now
            };

            await _repository.InsertAsync(newRecord);
        }
    }

    /// <summary>
    /// 获取指定员工的不可用统计数据
    /// </summary>
    public async Task<UnavailabilityStatistics> GetStatisticsAsync(long personnelId, DateTime startDate, DateTime endDate)
    {
        try
        {
            // 获取日期范围内的所有记录
            var records = await _repository.GetByPersonnelAndDateRangeAsync(personnelId, startDate, endDate);
            
            // 获取所有班次信息
            var shifts = await _shiftRepository.Select
                .Where(x => x.IsEnabled)
                .ToListAsync();

            var totalDays = (endDate.Date - startDate.Date).Days + 1;
            var totalPossibleSlots = totalDays * shifts.Count;

            var statistics = new UnavailabilityStatistics
            {
                PersonnelId = personnelId,
                StartDate = startDate,
                EndDate = endDate,
                TotalDays = totalDays,
                TotalRecords = records.Count,
                TotalPossibleSlots = totalPossibleSlots,
                UnavailableRate = totalPossibleSlots > 0 ? (double)records.Count / totalPossibleSlots * 100 : 0
            };

            // 按班次统计
            statistics.ShiftStatistics = shifts.Select(shift => new ShiftStatistics
            {
                ShiftId = shift.Id,
                ShiftName = shift.Name,
                Count = records.Count(r => r.ShiftId == shift.Id),
                Percentage = totalDays > 0 ? (decimal)((double)records.Count(r => r.ShiftId == shift.Id) / totalDays * 100) : 0
            }).ToList();

            // 按原因类型统计
            statistics.ReasonTypeStatistics = records
                .GroupBy(r => (UnavailabilityReasonType)r.ReasonType)
                .Select(g => new ReasonTypeStatistics
                {
                    ReasonType = g.Key,
                    Count = g.Count(),
                    Percentage = records.Count > 0 ? (decimal)((double)g.Count() / records.Count * 100) : 0,
                    AffectedDays = g.Select(r => r.Date.Date).Distinct().Count()
                }).OrderByDescending(s => s.Count).ToList();

            // 按分类统计
            statistics.CategoryStatistics = records
                .GroupBy(r => ((UnavailabilityReasonType)r.ReasonType).GetCategory())
                .Select(g => new CategoryStatistics
                {
                    Category = g.Key,
                    Count = g.Count(),
                    Percentage = records.Count > 0 ? (decimal)((double)g.Count() / records.Count * 100) : 0,
                    AffectedDays = g.Select(r => r.Date.Date).Distinct().Count(),
                    ReasonTypes = g.Select(r => (UnavailabilityReasonType)r.ReasonType).Distinct().ToList()
                }).OrderByDescending(s => s.Count).ToList();

            // 按星期几统计
            statistics.WeekdayStatistics = records
                .GroupBy(r => r.Date.DayOfWeek)
                .Select(g => new WeekdayStatistics
                {
                    DayOfWeek = g.Key,
                    DayName = GetWeekdayName(DateTime.Today.AddDays((int)g.Key - (int)DateTime.Today.DayOfWeek)),
                    Count = g.Count(),
                    AffectedDates = g.Select(r => r.Date.Date).Distinct().Count()
                }).OrderBy(s => s.DayOfWeek).ToList();

            // 模板生成统计
            var templateRecords = records.Where(r => r.IsFromTemplate).ToList();
            statistics.TemplateStatistics = new TemplateStatistics
            {
                TotalTemplateRecords = templateRecords.Count,
                TemplateGeneratedRate = records.Count > 0 ? (decimal)((double)templateRecords.Count / records.Count * 100) : 0,
                ManualCreatedRecords = records.Count - templateRecords.Count,
                ManualCreatedRate = records.Count > 0 ? (decimal)((double)(records.Count - templateRecords.Count) / records.Count * 100) : 0
            };

            // 月度趋势（如果时间范围超过一个月）
            if (totalDays > 31)
            {
                statistics.MonthlyTrend = records
                    .GroupBy(r => new { Year = r.Date.Year, Month = r.Date.Month })
                    .Select(g => new MonthlyTrendItem
                    {
                        Year = g.Key.Year,
                        Month = g.Key.Month,
                        Count = g.Count(),
                        UnavailableDays = g.Select(r => r.Date.Date).Distinct().Count(),
                        MonthDisplay = $"{g.Key.Year}年{g.Key.Month:00}月"
                    }).OrderBy(t => t.Year).ThenBy(t => t.Month).ToList();
            }

            return statistics;
        }
        catch (Exception ex)
        {
            throw new Exception($"获取统计数据失败: {ex.Message}", ex);
        }
    }

    /// <summary>
    /// 获取团队成员的不可用报告
    /// </summary>
    public async Task<List<UnavailabilityStatistics>> GetTeamReportAsync(List<long> personnelIds, DateTime month)
    {
        try
        {
            var monthStart = new DateTime(month.Year, month.Month, 1);
            var monthEnd = monthStart.AddMonths(1).AddDays(-1);

            var teamReports = new List<UnavailabilityStatistics>();

            // 并发获取每个成员的统计数据
            var tasks = personnelIds.Select(async personnelId =>
            {
                var statistics = await GetStatisticsAsync(personnelId, monthStart, monthEnd);
                return statistics;
            });

            var results = await Task.WhenAll(tasks);
            teamReports.AddRange(results);

            // 对结果按不可用率排序
            return teamReports.OrderByDescending(r => r.UnavailableRate).ToList();
        }
        catch (Exception ex)
        {
            throw new Exception($"获取团队报告失败: {ex.Message}", ex);
        }
    }

    #endregion
}