package com.sundot.airport.item.utils;

import com.sundot.airport.common.core.domain.entity.SysDept;
import com.sundot.airport.item.domain.SimpleDutySchedule;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 统一值班排班调度器
 * 支持多种排班模式：
 * 1. 单班模式：如9点到次日9点（24小时值班）
 * 2. 两班倒模式：如9-17, 17-9
 *
 * @author wangxx
 * @date 2026-01-14
 */
public class UnifiedDutyScheduler {

    /**
     * 生成统一排班计划
     *
     * @param startDate         起始日期
     * @param startDepartment   起始部门
     * @param departments       循环排岗部门信息列表
     * @param shifts            班次安排数组，每个元素包含[startHour, endHour]
     * @param daysToGenerate    生成天数
     * @param stationDepartment 站点部门对象，包含站点ID和名称
     * @return SimpleDutySchedule列表
     */
    public static List<SimpleDutySchedule> generateUnifiedSchedule(Date startDate, SysDept startDepartment, List<SysDept> departments, int[][] shifts, int daysToGenerate, SysDept stationDepartment) {
        List<SimpleDutySchedule> scheduleList = new ArrayList<>();

        // 提取部门名称数组和部门ID数组
        String[] deptNames = departments.stream()
                .map(SysDept::getDeptName)
                .toArray(String[]::new);
        Long[] departmentIds = departments.stream()
                .map(SysDept::getDeptId)
                .toArray(Long[]::new);

        // 验证部门ID数组长度是否与部门名称数组一致
        if (departmentIds != null && departmentIds.length != deptNames.length) {
            throw new IllegalArgumentException("部门ID数组长度与部门名称数组长度不匹配");
        }

        // 获取起始部门名称
        String startDeptName = startDepartment != null ? startDepartment.getDeptName() : null;

        if (startDeptName == null) {
            throw new IllegalArgumentException("未找到指定的起始部门名称");
        }

        // 找到起始科室的索引
        int startIndex = -1;
        for (int i = 0; i < deptNames.length; i++) {
            if (deptNames[i].equals(startDeptName)) {
                startIndex = i;
                break;
            }
        }

        if (startIndex == -1) {
            throw new IllegalArgumentException("未找到指定的起始科室: " + startDeptName);
        }

        // 从起始日期开始生成排班
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);

        int currentDeptIndex = startIndex;

        // 计算总的班次数
        int totalShifts = daysToGenerate * shifts.length;

        for (int i = 0; i < totalShifts; i++) {
            // 确定当前是哪一天的第几个班次
            int dayIndex = i / shifts.length; // 第几天
            int shiftIndex = i % shifts.length; // 当天的第几个班次

            // 获取班次信息 [startHour, endHour]
            int[] shift = shifts[shiftIndex];
            int startTime = shift[0];
            int endTime = shift[1];

            // 计算班次日期
            Calendar shiftCalendar = (Calendar) calendar.clone();
            shiftCalendar.add(Calendar.DAY_OF_MONTH, dayIndex);

            // 判断是否跨天
            boolean isCrossDay = false;
            if (startTime > endTime) {
                // 如果开始时间大于结束时间，说明跨天，例如22点到次日6点
                isCrossDay = true;
            } else if (startTime == endTime && shifts.length == 1) {
                // 对于24小时连续值班情况，如9点到次日9点，由于是一整天(24小时)值班，所以肯定跨天
                isCrossDay = true;
            }

            // 确定当前班次的科室
            int deptIndex = (currentDeptIndex + shiftIndex) % deptNames.length; // 同一天内不同班次也轮换科室

            // 创建班次安排
            SimpleDutySchedule shiftSchedule = new SimpleDutySchedule();
            shiftSchedule.setStationId(stationDepartment.getDeptId());
            shiftSchedule.setStationName(stationDepartment.getDeptName());

            if (departmentIds != null && departmentIds.length > deptIndex) {
                shiftSchedule.setDepartmentId(departmentIds[deptIndex]);

                // 使用部门信息列表中的名称
                SysDept dept = departments.get(deptIndex);
                if (dept != null) {
                    shiftSchedule.setDepartmentName(dept.getDeptName());
                } else {
                    shiftSchedule.setDepartmentName(deptNames[deptIndex]); // fallback to name array
                }
            } else {
                shiftSchedule.setDepartmentName(deptNames[deptIndex]);
            }
            shiftSchedule.setDutyDate(shiftCalendar.getTime());

            // 设置完整的开始时间
            Calendar startCal = (Calendar) shiftCalendar.clone();
            startCal.set(Calendar.HOUR_OF_DAY, startTime);
            startCal.set(Calendar.MINUTE, 0);
            startCal.set(Calendar.SECOND, 0);
            startCal.set(Calendar.MILLISECOND, 0);
            shiftSchedule.setStartTime(startCal.getTime());

            // 设置完整的结束时间
            Calendar endCal = (Calendar) shiftCalendar.clone();
            if (isCrossDay) {
                endCal.add(Calendar.DAY_OF_MONTH, 1);
            }
            endCal.set(Calendar.HOUR_OF_DAY, endTime);
            endCal.set(Calendar.MINUTE, 0);
            endCal.set(Calendar.SECOND, 0);
            endCal.set(Calendar.MILLISECOND, 0);
            shiftSchedule.setEndTime(endCal.getTime());

            shiftSchedule.setCrossDay(isCrossDay ? 1 : 0);
            shiftSchedule.setStatus("0");
            scheduleList.add(shiftSchedule);

            // 根据班次安排模式决定何时轮换科室
            if (shiftIndex == shifts.length - 1) {
                // 每天结束后轮换科室
                currentDeptIndex = (currentDeptIndex + 1) % deptNames.length;
            }
        }

        return scheduleList;
    }

}