using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using NPP.SmartSchedue.Api.Contracts.Domain.Time;
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
using NPP.SmartSchedue.Api.Contracts.Services.Workbench;
using NPP.SmartSchedue.Api.Contracts.Services.Workbench.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Workbench.Output;
using NPP.SmartSchedue.Api.Contracts.Core.Enums;
using NPP.SmartSchedue.Api.Contracts.Core.Extensions;
using NPP.SmartSchedue.Api.Contracts;
using ZhonTai.Admin.Services;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using Microsoft.AspNetCore.Mvc;

namespace NPP.SmartSchedue.Api.Services.Workbench;

/// <summary>
/// 工作台服务实现
/// 提供工作台相关的数据查询和业务逻辑处理
/// </summary>
[DynamicApi(Area = "app")]
public class WorkbenchService : BaseService, IWorkbenchService, IDynamicApi
{
    private readonly IWorkOrderRepository _workOrderRepository;
    private readonly IShiftUnavailabilityRepository _shiftUnavailabilityRepository;
    private readonly IShiftRepository _shiftRepository;

    public WorkbenchService(
        IWorkOrderRepository workOrderRepository,
        IShiftUnavailabilityRepository shiftUnavailabilityRepository,
        IShiftRepository shiftRepository)
    {
        _workOrderRepository = workOrderRepository;
        _shiftUnavailabilityRepository = shiftUnavailabilityRepository;
        _shiftRepository = shiftRepository;
    }

    /// <summary>
    /// 获取用户本周日历数据
    /// 包含任务排班信息和班次不可用性信息，用于日历视图展示
    /// </summary>
    /// <param name="input">查询参数</param>
    /// <returns>本周日历数据</returns>
    [HttpPost]
    public async Task<WeeklyCalendarOutput> GetWeeklyCalendarAsync(WeeklyCalendarInput input)
    {
        // 1. 参数预处理和验证
        var currentUserId = User?.Id ?? throw new UnauthorizedAccessException("用户未登录");
        var targetPersonnelId = input.PersonnelId ?? currentUserId;
        var targetDate = input.WeekDate ?? DateTime.Now;
        
        // 2. 计算本周的开始和结束日期（周一到周日）
        var weekStartDate = GetWeekStartDate(targetDate);
        var weekEndDate = weekStartDate.AddDays(6);
        
        // 3. 并行查询数据
        var tasksTask = GetWeeklyTasksAsync(targetPersonnelId, weekStartDate, weekEndDate, input.IncludeCompletedTasks);
        var unavailabilitiesTask = input.IncludeUnavailableSlots 
            ? GetWeeklyUnavailabilitiesAsync(targetPersonnelId, weekStartDate, weekEndDate)
            : Task.FromResult(new List<ShiftUnavailabilityEntity>());
        var shiftsTask = GetAllActiveShiftsAsync();
        
        await Task.WhenAll(tasksTask, unavailabilitiesTask, shiftsTask);
        
        var tasks = await tasksTask;
        var unavailabilities = await unavailabilitiesTask;
        var shifts = await shiftsTask;
        
        // 4. 构建日历数据结构
        var result = new WeeklyCalendarOutput
        {
            WeekStartDate = weekStartDate,
            WeekEndDate = weekEndDate,
            PersonnelId = targetPersonnelId,
            PersonnelName = "当前用户", // TODO: 从用户服务获取用户名
            Days = new List<CalendarDayItem>()
        };
        
        // 5. 按天组织数据
        for (int dayOffset = 0; dayOffset < 7; dayOffset++)
        {
            var currentDate = weekStartDate.AddDays(dayOffset);
            var dayItem = new CalendarDayItem
            {
                Date = currentDate,
                DayOfWeek = (int)currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek,
                DayOfWeekName = GetDayOfWeekName((int)currentDate.DayOfWeek == 0 ? 7 : (int)currentDate.DayOfWeek),
                Shifts = new List<CalendarShiftItem>()
            };
            
            // 6. 为每一天的每个班次构建数据
            foreach (var shift in shifts.OrderBy(s => s.StartTime))
            {
                var shiftItem = new CalendarShiftItem
                {
                    ShiftId = shift.Id,
                    ShiftName = shift.Name,
                    StartTime = shift.StartTime,
                    EndTime = shift.EndTime,
                    Tasks = new List<CalendarTaskItem>(),
                    UnavailableItems = new List<CalendarUnavailableItem>()
                };
                
                // 7. 填充当前班次的任务数据
                var dayTasks = tasks.Where(t => t.WorkOrderDate.Date == currentDate.Date 
                                              && t.ShiftId == shift.Id).ToList();
                foreach (var task in dayTasks)
                {
                    shiftItem.Tasks.Add(new CalendarTaskItem
                    {
                        TaskId = task.Id,
                        TaskCode = task.WorkOrderCode ?? task.Code ?? "",
                        ProjectNumber = task.ProjectNumber ?? "",
                        ProcessName = task.ProcessName ?? "",
                        Status = task.Status,
                        StatusName = ((WorkOrderStatusEnum)task.Status).ToString(),
                        Priority = task.Priority,
                        EstimatedHours = task.EstimatedHours,
                        PlannedStartTime = task.PlannedStartTime,
                        PlannedEndTime = task.PlannedEndTime,
                        Remarks = task.Remarks ?? ""
                    });
                }
                
                // 8. 填充当前班次的不可用时间段数据
                var dayUnavailabilities = unavailabilities.Where(u => u.Date.Date == currentDate.Date 
                                                                     && u.ShiftId == shift.Id).ToList();
                foreach (var unavailability in dayUnavailabilities)
                {
                    shiftItem.UnavailableItems.Add(new CalendarUnavailableItem
                    {
                        UnavailabilityId = unavailability.Id,
                        ReasonType = unavailability.ReasonType,
                        ReasonTypeName = unavailability.ReasonType.GetDisplayName(),
                        Remark = unavailability.Remark ?? "",
                        EffectiveStartTime = unavailability.EffectiveStartTime,
                        EffectiveEndTime = unavailability.EffectiveEndTime,
                        Priority = unavailability.Priority
                    });
                }
                
                dayItem.Shifts.Add(shiftItem);
            }
            
            result.Days.Add(dayItem);
        }
        
        return result;
    }

    #region 私有辅助方法
    
    /// <summary>
    /// 获取指定日期所在周的周一日期
    /// </summary>
    /// <param name="date">指定日期</param>
    /// <returns>周一日期</returns>
    private static DateTime GetWeekStartDate(DateTime date)
    {
        var dayOfWeek = (int)date.DayOfWeek;
        if (dayOfWeek == 0) dayOfWeek = 7; // 将周日从0调整为7
        return date.AddDays(-(dayOfWeek - 1)).Date;
    }
    
    /// <summary>
    /// 获取星期几的中文名称
    /// </summary>
    /// <param name="dayOfWeek">星期几（1=周一，7=周日）</param>
    /// <returns>中文名称</returns>
    private static string GetDayOfWeekName(int dayOfWeek)
    {
        return dayOfWeek switch
        {
            1 => "周一",
            2 => "周二", 
            3 => "周三",
            4 => "周四",
            5 => "周五",
            6 => "周六",
            7 => "周日",
            _ => ""
        };
    }
    
    /// <summary>
    /// 获取指定人员本周的工作任务
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <param name="weekStartDate">周开始日期</param>
    /// <param name="weekEndDate">周结束日期</param>
    /// <param name="includeCompleted">是否包含已完成任务</param>
    /// <returns>任务列表</returns>
    private async Task<List<WorkOrderEntity>> GetWeeklyTasksAsync(long personnelId, DateTime weekStartDate, DateTime weekEndDate, bool includeCompleted)
    {
        // 构建查询条件
        var query = _workOrderRepository.Where(t => 
            t.AssignedPersonnelId == personnelId &&
            t.WorkOrderDate >= weekStartDate &&
            t.WorkOrderDate <= weekEndDate);
        
        // 根据参数决定是否过滤已完成任务
        if (!includeCompleted)
        {
            query = query.Where(t => t.Status != (int)WorkOrderStatusEnum.Completed);
        }
        
        // 执行查询并包含相关实体
        var tasks = await query
            .Include(t => t.ProcessEntity)
            .Include(t => t.ShiftEntity)
            .OrderBy(t => t.WorkOrderDate)
            .OrderBy(t => t.PlannedStartTime)
            .ToListAsync();
            
        return tasks;
    }
    
    /// <summary>
    /// 获取指定人员本周的班次不可用记录
    /// </summary>
    /// <param name="personnelId">人员ID</param>
    /// <param name="weekStartDate">周开始日期</param>
    /// <param name="weekEndDate">周结束日期</param>
    /// <returns>不可用记录列表</returns>
    private async Task<List<ShiftUnavailabilityEntity>> GetWeeklyUnavailabilitiesAsync(long personnelId, DateTime weekStartDate, DateTime weekEndDate)
    {
        var unavailabilities = await _shiftUnavailabilityRepository.Where(u => 
            u.PersonnelId == personnelId &&
            u.Date >= weekStartDate &&
            u.Date <= weekEndDate)
            .OrderBy(u => u.Date)
            .OrderBy(u => u.Priority)
            .ToListAsync();
            
        return unavailabilities;
    }
    
    /// <summary>
    /// 获取所有活跃的班次
    /// </summary>
    /// <returns>班次列表</returns>
    private async Task<List<ShiftEntity>> GetAllActiveShiftsAsync()
    {
        var shifts = await _shiftRepository.Where(s => s.IsEnabled)
            .OrderBy(s => s.StartTime)
            .ToListAsync();
            
        return shifts;
    }
    
    #endregion
}