package com.ruoyi.zhushi.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.dto.RoleDTO;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.zhushi.entity.*;
import com.ruoyi.zhushi.mapper.DkRecordMapper;
import com.ruoyi.zhushi.service.DkRecordService;
import com.ruoyi.zhushi.util.CalendarGenerator;
import com.ruoyi.zhushi.util.Constans;
import com.ruoyi.zhushi.util.TimeUtils;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.*;

@Service
public class DkRecordServiceImpl implements DkRecordService {
    @Autowired
    private DkRecordMapper dkMapper;

    public String getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date currentDate = new Date();
        return sdf.format(currentDate);
    }

    @Override
    public TableDataInfo<DkCheckInRecordDTO> queryPageList(DkCheckInRecordDTO dkCheckInRecordDTO, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = buildQueryWrapper(dkCheckInRecordDTO, null);
        if (dkCheckInRecordDTO.getFlag().equals("my")){
            if (loginUser == null) {
                return TableDataInfo.build();
            }else {
                // 获取用户角色
                List<RoleDTO> roles = loginUser.getRoles();
                if (roles != null && roles.size() > 0) {
                    for (RoleDTO role : roles) {
                        if (role.getRoleKey().equals(Constans.ROLEKEY)) {
                            queryWrapper.eq(DkCheckInRecord::getSysUserId, loginUser.getUserId());
                        }
                    }
                }
            }
        }

        Page<DkCheckInRecordDTO> result = dkMapper.selectVoPage(pageQuery.build(), queryWrapper);
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<DkCheckInRecord> buildQueryWrapper(DkCheckInRecordDTO dkCheckInRecordDTO, String flag) {
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = Wrappers.lambdaQuery();

        queryWrapper.eq(null != dkCheckInRecordDTO.getSysUserId() ,DkCheckInRecord::getSysUserId, dkCheckInRecordDTO.getSysUserId());
        queryWrapper.eq(null != dkCheckInRecordDTO.getSysUserName() ,DkCheckInRecord::getSysUserName, dkCheckInRecordDTO.getSysUserName());
        queryWrapper.eq(null != dkCheckInRecordDTO.getCheckInTime(), DkCheckInRecord::getCheckInTime, dkCheckInRecordDTO.getCheckInTime());
        if (null != dkCheckInRecordDTO.getCheckInStatus()) {
            queryWrapper.eq(null != dkCheckInRecordDTO.getCheckInStatus(), DkCheckInRecord::getClockInStatus,
                dkCheckInRecordDTO.getCheckInStatus()).or().eq(null != dkCheckInRecordDTO.getCheckInStatus(),
                DkCheckInRecord::getClockOutStatus, dkCheckInRecordDTO.getCheckInStatus());
        }

//        queryWrapper.eq(null != dkCheckInRecordDTO.getExportRange(), DkCheckInRecord::getExportRange, dkCheckInRecordDTO.getExportRange());
        if(dkCheckInRecordDTO.getStrDay() != null){
            queryWrapper.between(DkCheckInRecord::getCheckInTime, TimeUtils.getStartTime(dkCheckInRecordDTO.getStrDay()),
                TimeUtils.getEndTime(dkCheckInRecordDTO.getStrDay()));
        }
        if(dkCheckInRecordDTO.getStrMonth() != null){
            queryWrapper.between(DkCheckInRecord::getCheckInTime, TimeUtils.getFirstDayOfMonth(dkCheckInRecordDTO.getStrMonth()),
                TimeUtils.getLastDayOfMonth(dkCheckInRecordDTO.getStrMonth()));
        }
        if(flag != null){
            queryWrapper.select(DkCheckInRecord::getSysUserName, DkCheckInRecord::getSysUserId, DkCheckInRecord::getNickName);
            queryWrapper.in(null != dkCheckInRecordDTO.getAttendanceGroupIds() ,DkCheckInRecord::getAttendanceGroupId, dkCheckInRecordDTO.getAttendanceGroupIds());
            queryWrapper.groupBy(DkCheckInRecord::getSysUserName).groupBy(DkCheckInRecord::getSysUserId).groupBy(DkCheckInRecord::getNickName);
        }else{
            queryWrapper.orderByDesc(DkCheckInRecord::getSysUserName).orderByDesc(DkCheckInRecord::getCheckInTime);
        }
        return queryWrapper;
    }


    /**
     * 查询预警结果列表
     */
    @Override
    public List<DkCheckInRecordDTO> queryList(DkCheckInRecordDTO dkCheckInRecordDTO) {
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = buildQueryWrapper(dkCheckInRecordDTO, null);
        List<DkCheckInRecordDTO> dkCheckInRecordDTOS = dkMapper.selectVoList(queryWrapper);
        dkCheckInRecordDTOS.forEach(dk -> {
            if("0".equals(dk.getCheckInStatus())){
                dk.setCheckInStatus("正常");
            }
            if("1".equals(dk.getCheckInStatus())){
                dk.setCheckInStatus("迟到");
            }
            if("2".equals(dk.getCheckInStatus())){
                dk.setCheckInStatus("缺卡");
            }
        });
        return dkCheckInRecordDTOS;
    }

    /**
     * 导出考勤 excel
     * @param dkCheckInRecordDTO
     * @param response
     */
    @Override
    public void exportNew(DkCheckInRecordDTO dkCheckInRecordDTO, HttpServletResponse response) {
        // 当前日期
        LocalDate now = LocalDate.now();

        // 校验月份
        YearMonth inputMonth = YearMonth.parse(dkCheckInRecordDTO.getStrMonth()); // e.g. "2025-08"
        YearMonth currentMonth = YearMonth.from(now);

        if (inputMonth.isAfter(currentMonth)) {
            return ;
        }

        // 如果传了 strDay，再校验日期
        if (StringUtils.isNotBlank(dkCheckInRecordDTO.getStrDay())) {
            LocalDate inputDay = LocalDate.parse(dkCheckInRecordDTO.getStrDay()); // e.g. "2025-07-10"
            if (inputDay.isAfter(now)) {
                return;
            }
        }

        // 查询出所有人员
        List<JSONObject> jsonObjects = dkMapper.queryAllUsers(dkCheckInRecordDTO.getAttendanceGroupIds());
        if(jsonObjects==null||jsonObjects.size() == 0){
            return;
        }
        //转换对象格式
        List<DkCheckInRecordDTO> dkCheckInRecordDTOS = new ArrayList<>();
        for (JSONObject jsonObject:jsonObjects) {
            DkCheckInRecordDTO dto = new DkCheckInRecordDTO();
            dto.setSysUserId((Long)jsonObject.get("userId"));
            dto.setSysUserName((String)jsonObject.get("userName"));
            dto.setNickName((String)jsonObject.get("nickName"));
            dkCheckInRecordDTOS.add(dto);
        }

        try {
            InputStream inputStream = null;
            Workbook workbook;
            // 定义迟到人数
            int latePersonCount = 0;
            // 定义早退人数
            int earlyPersonCount = 0;
            // 定义迟到次数
            int lateCount = 0;
            // 定义早退次数
            int earlyCount = 0;
            // 加载模板文件
            if(Constans.GUONEI.equals(dkCheckInRecordDTO.getModelType())){
                ClassPathResource resource = new ClassPathResource("template/template-guonei.xlsx");
                inputStream = resource.getInputStream();
            }
            if(Constans.RIBEN.equals(dkCheckInRecordDTO.getModelType())){
                ClassPathResource resource = new ClassPathResource("template/template-riben.xlsx");
                inputStream = resource.getInputStream();
            }
            workbook = WorkbookFactory.create(inputStream);

            // 遍历所有人员
            for (int i = 0; i <= dkCheckInRecordDTOS.size(); i++){
                int newSheetIndex = workbook.getNumberOfSheets();
                if(i == dkCheckInRecordDTOS.size()){
                    //国内有汇总
                    if (Constans.GUONEI.equals(dkCheckInRecordDTO.getModelType())) {
                        workbook.createSheet("汇总");
                        workbook.setSheetName(newSheetIndex, "汇总");
                        // 获取新创建的Sheet
                        Sheet newSheet = workbook.getSheetAt(newSheetIndex);
                        fillTemplateHuiZong(newSheet, latePersonCount, earlyPersonCount, lateCount, earlyCount);
                    }
                }else{
                    DkCheckInRecordDTO dk = dkCheckInRecordDTOS.get(i);
                    workbook.cloneSheet(0);
                    workbook.setSheetName(newSheetIndex, dk.getNickName() != null ? dk.getNickName() : dk.getSysUserName());

                    // 获取新创建的Sheet
                    Sheet newSheet = workbook.getSheetAt(newSheetIndex);

                    // 准备数据
                    dkCheckInRecordDTO.setSysUserId(dk.getSysUserId());
                    dkCheckInRecordDTO.setSysUserName(dk.getSysUserName());
                    dkCheckInRecordDTO.setNickName(dk.getNickName());
                    // 国内模版
                    if(Constans.GUONEI.equals(dkCheckInRecordDTO.getModelType())){
                        // 构造导出数据
                        EmployeeAttendance attendanceData = prepareSampleData(dkCheckInRecordDTO);
                        if(attendanceData.getChidaocishu() > 0){
                            latePersonCount ++;
                            lateCount = lateCount + attendanceData.getChidaocishu();
                        }
                        if(attendanceData.getZaotuicishu() > 0){
                            earlyPersonCount ++;
                            earlyCount = earlyCount + attendanceData.getZaotuicishu();
                        }
                        // 填充数据到模板
                        if (attendanceData.getDayRecords().size() == 0){
                            return;
                        }
                        fillTemplate(newSheet, attendanceData);
                    }
                    // 日本模版
                    if(Constans.RIBEN.equals(dkCheckInRecordDTO.getModelType())){
                        // 构造导出数据
                        EmployeeAttendance attendanceData = prepareSampleDataRiBen(dkCheckInRecordDTO);
                        // 填充数据到模板
/*                        if (attendanceData.getDayRecords().size() == 0){
                            break;
                        }*/
                        fillTemplateRiBen(newSheet, attendanceData);
                    }
                }
            }

            workbook.removeSheetAt(0);
            workbook.write(response.getOutputStream());
            workbook.close();
            inputStream.close();
            System.out.println("Excel 导出成功！");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*--------------------------------------------------国内汇总信息 --------------------------*/
    private void fillTemplateHuiZong(Sheet sheet, int latePersonCount, int earlyPersonCount, int lateCount,
                                     int earlyCount) {

        setCellValue(sheet, 0, 1, "人数");
        setCellValue(sheet, 0, 2, "次数");
        setCellValue(sheet, 1, 0, "迟到");
        setCellValue(sheet, 2, 0, "早退");
        setCellValue(sheet, 1, 1, latePersonCount);
        setCellValue(sheet, 1, 2, lateCount);
        setCellValue(sheet, 2, 1, earlyPersonCount);
        setCellValue(sheet, 2, 2, earlyCount);

    }

    /*---------------------------------------------------国内 --------------------------*/
    private EmployeeAttendance prepareSampleData(DkCheckInRecordDTO dkCheckInRecordDTO) {

        // 定义员工类对象
        EmployeeAttendance data = new EmployeeAttendance();
        // 设置员工的昵称
        data.setEmployeeName(dkCheckInRecordDTO.getNickName());
        // 设置员工的用户名
        data.setUserName(dkCheckInRecordDTO.getSysUserName());

        // 判断月日是否为空
        if(dkCheckInRecordDTO.getStrMonth() != null){
            data.setDateTime(formatDate(dkCheckInRecordDTO.getStrMonth()));
        }
        if(dkCheckInRecordDTO.getStrDay() != null){
            data.setDateTime(convertToChineseFormat(dkCheckInRecordDTO.getStrDay()));
        }

        //根据userId获取打卡配置信息
        DkAttendanceGroup dkAttendanceGroup = dkMapper.queryConfigByUserId(dkCheckInRecordDTO.getSysUserId());

/*        // 是否允许迟到
        Boolean allowLate = dkAttendanceGroup.getAllowLate();
        // 允许迟到的时长
        Integer lateRange = dkAttendanceGroup.getLateRange();
        // 是否允许早退
        Boolean allowEarly = dkAttendanceGroup.getAllowEarly();
        // 允许早退的时长
        Integer earlyRange = dkAttendanceGroup.getEarlyRange();*/


        // 定义集合，用于存储每天打卡记录
        List<DayRecord> dayRecords = new ArrayList<>();
        // 根据用户的ID查询该用户所有的打卡记录
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = buildQueryWrapper(dkCheckInRecordDTO, null);
        List<DkCheckInRecordDTO> dkCheckInRecordDTOS = dkMapper.selectVoList(queryWrapper);
        if (dkCheckInRecordDTOS == null && dkCheckInRecordDTOS.isEmpty()){
            return data;
        }

        // 构造excel数据
        // 定义迟到次数
        int lateCount = 0;
        // 定义早退次数
        int earlyCount = 0;
        // 工作日加班时间
        BigDecimal workOverTime = new BigDecimal(0);
        // 休息日加班时间
        BigDecimal restOverTime = new BigDecimal(0);
        // 异常数量
        BigDecimal exceptionCount = new BigDecimal(0);

        for(DkCheckInRecordDTO dk : dkCheckInRecordDTOS){
            // 根据打卡时间获取日期
            LocalDate localDate = dk.getCheckInTime() != null ? dk.getCheckInTime().toLocalDate() : LocalDate.now();
            // 获取所属考勤组的上班打卡时间
            String workStartTime = dkAttendanceGroup.getWorkStartTime();
            LocalDateTime workStartTime1 = LocalDateTime.of(localDate, LocalTime.parse(workStartTime));
            // 获取所属考勤组的下班打卡时间
            String workEndTime = dkAttendanceGroup.getWorkEndTime();
            LocalDateTime workEndTime1 = LocalDateTime.of(localDate, LocalTime.parse(workEndTime));

            // 获取所属考勤组的午休开始时间
            String lunchStartTime = dkAttendanceGroup.getLunchStartTime();
            LocalDateTime lunchStartTime1 = LocalDateTime.of(localDate, LocalTime.parse(lunchStartTime));
            // 获取所属考勤组的午休结束时间
            String lunchEndTime = dkAttendanceGroup.getLunchEndTime();
            LocalDateTime lunchEndTime1 = LocalDateTime.of(localDate, LocalTime.parse(lunchEndTime));
            // 获取所属考勤组的午休时间
            String lunchTime = dkAttendanceGroup.getLunchTime();

            // 构造DayRecord
            DayRecord dayRecord = new DayRecord();
            dayRecord.setDay(localDate.getDayOfMonth());
            // 获取星期几（返回 DayOfWeek 枚举）
            DayOfWeek dayOfWeek = localDate.getDayOfWeek();
            int week = dayOfWeek.getValue();
            String chineseWeek = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINESE);
            //System.out.println("中文星期：" + chineseWeek); // 输出：星期三
            dayRecord.setWeekday(chineseWeek);
            dayRecord.setStartTime(null != dk.getClockIn() ? dk.getClockIn().format(DateTimeFormatter.ofPattern("HH:mm:ss")) : "");
            dayRecord.setEndTime(null != dk.getClockOut() ? dk.getClockOut().format(DateTimeFormatter.ofPattern("HH:mm:ss")) : "");
            // 迟到早退判断
            if(dk.getClockIn() != null && dk.getClockOut() != null){
                if(dk.getClockIn().isAfter(workStartTime1)){
                    dayRecord.setChidao("●");
                    dayRecord.setRemark("迟到1次");
                    lateCount ++;
                }

                if(dk.getClockOut().isBefore(workEndTime1)){
                    earlyCount ++;
                }
            }
            // 异常打卡 只有上班 没有下班
            if(dk.getClockIn() != null && dk.getClockOut() == null){
                dayRecord.setYichang("●");
                dayRecord.setRemark("异常打卡");
                exceptionCount = exceptionCount.add(new BigDecimal(1));
                //如果只有上班没有下班 而且上班还迟到了
                if(dk.getClockIn().isAfter(workStartTime1)){
                    dayRecord.setChidao("●");
                    lateCount ++;
                }
            }

            // 判断是否为休假日加班
            if(Constans.EXPORT_ZHOULIU==week || Constans.EXPORT_ZHOURI== week){
                //上下班都打卡了
                if(dk.getClockIn() != null && dk.getClockOut() != null){
                    double Overtime = 0;
                    if (dk.getClockIn().isBefore(lunchStartTime1)) {
                        // 午休之前 打卡时间在规定上班时间后 使用打卡时间 否则使用规定上班时间 计算
                        Overtime = calculateOvertime(dk.getClockIn().isAfter(workStartTime1)?dk.getClockIn():workStartTime1,
                            dk.getClockOut(),Double.valueOf(lunchTime));

                    }else if (dk.getClockIn().isAfter(lunchStartTime1)){
                        //午休之后 打卡时间计算
                        Overtime = calculateOvertime(dk.getClockIn(),dk.getClockOut(),0);
                    } else {
                        //午休中 使用午休结束时间计算
                        Overtime = calculateOvertime(lunchEndTime1,dk.getClockOut(),0);
                    }
                    //转换时间格式
                    dayRecord.setXiuxiri(formatOvertime(Overtime));
                    //休息日加班合计
                    restOverTime = restOverTime.add(new BigDecimal(Overtime));
                }
            }else {
                // 判断是否为工作日加班
                if(dk.getClockOut() != null){
                    if(dk.getClockOut().isAfter(workEndTime1)){
                        // 计算时间差 规定的下班打卡时间 和下班打卡时间差值
                        double Overtime = calculateOvertime(workEndTime1,dk.getClockOut(),0.5);
                        dayRecord.setGongzuori(formatOvertime(Overtime));
                        //工作日加班合计
                        workOverTime = workOverTime.add(new BigDecimal(Overtime));
                    }
                }
            }
            // 判断是否为法定节假日加班
            dayRecords.add(dayRecord);
        }

        data.setChidaocishu(lateCount);
        data.setZaotuicishu(earlyCount);
        data.setWorkOverTime(workOverTime);
        data.setRestOverTime(restOverTime);
        data.setExceptionCount(exceptionCount);
        data.setDayRecords(dayRecords);
        return data;
    }

    private void fillTemplate(Sheet sheet, EmployeeAttendance data) {
        // 1.填充标题区域
        setCellValue(sheet, 6, 6, data.getUserName());
        setCellValue(sheet, 6, 10, data.getEmployeeName());
        setCellValue(sheet, 3, 1, data.getDateTime());

        //2.考勤数据区域
        //2.1 生成全部的日期和星期 并设置颜色
        int year = LocalDate.now().getYear();
        int month = LocalDate.now().getMonthValue();
        int rowIndex = 10;
        Map<Integer, List<CalendarGenerator.DayInfo>> calendar = CalendarGenerator.generateYearCalendar(year);
        List<CalendarGenerator.DayInfo> dayInfos = calendar.get(month);
        for (int i = 0; i < dayInfos.size(); i++) {
            rowIndex = i + 10;
            //初始化天数
            setCellValue(sheet, rowIndex, 1, dayInfos.get(i).getDay());
            //初始化星期
            String weekName = dayInfos.get(i).getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE);
            setCellValue(sheet, rowIndex, 2, weekName);
            // 星期六和星期日背景颜色设置
            if ("星期六".equals(weekName) || "星期日".equals(weekName)) {
                Row row = sheet.getRow(rowIndex);
                if (row == null) row = sheet.createRow(rowIndex);
                Cell cell = row.getCell(2);
                if (cell == null) {
                    cell = row.createCell(2);
                }
                Workbook workbook = sheet.getWorkbook();
                CellStyle style = workbook.createCellStyle();
                style.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
                style.setFillForegroundColor(IndexedColors.RED.getIndex());
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                cell.setCellStyle(style);
            }
        }
        //2.2 考勤数据赋值
        for (DayRecord record : data.getDayRecords()) {
            if(record.getDay() >0 &&record.getDay()<=31){
                //从第十行开始 赋值 例如 第一天在第十行 所以+9
                fillTemplateCell(sheet, record.getDay()+9, record);
            }
        }

        //3. 汇总数据区域
        setCellValue(sheet, 41, 5, data.getChidaocishu());
        setCellValue(sheet, 41, 7, data.getExceptionCount());
        setCellValue(sheet, 41, 8, formatOvertime(data.getWorkOverTime()==null?0:data.getWorkOverTime().doubleValue()));
        setCellValue(sheet, 41, 9, formatOvertime(data.getRestOverTime()==null?0:data.getRestOverTime().doubleValue()));
    }

    private void fillTemplateCell(Sheet sheet, int rowIndex, DayRecord record) {
        setCellValue(sheet, rowIndex, 3, record.getStartTime());
        setCellValue(sheet, rowIndex, 4, record.getEndTime());
        setCellValue(sheet, rowIndex, 5, record.getChidao());
        //第六列 早退 暂时不需要了
        setCellValue(sheet, rowIndex, 7, record.getYichang());
        setCellValue(sheet, rowIndex, 8, record.getGongzuori());
        setCellValue(sheet, rowIndex, 9, record.getXiuxiri());
        setCellValue(sheet, rowIndex, 10, record.getFadingjiari());
        setCellValue(sheet, rowIndex, 11, record.getXiuxi());
        setCellValue(sheet, rowIndex, 12, record.getQingjia());
        setCellValue(sheet, rowIndex, 13, record.getRemark());
    }
    //查询两个时间的时间差 以0.5为准 多的按0.5算 少的 为0
    public static Double getHalfHourDiffAsCleanString(String startTime, String endTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime start = LocalDateTime.parse(startTime, formatter);
        LocalDateTime end = LocalDateTime.parse(endTime, formatter);

        long seconds = Duration.between(start, end).getSeconds();
        double hours = seconds / 3600.0;

        // 每0.5小时为单位，舍去不足
        double stepped = Math.floor(hours * 2) / 2.0;
        return stepped;
    }

    /*--------------------------------------------------日本 --------------------------*/

    private EmployeeAttendance prepareSampleDataRiBen(DkCheckInRecordDTO dkCheckInRecordDTO) {

        // 定义员工类对象
        EmployeeAttendance data = new EmployeeAttendance();
        // 设置员工的昵称
        data.setEmployeeName(dkCheckInRecordDTO.getNickName());
        // 设置员工的用户名
        data.setUserName(dkCheckInRecordDTO.getSysUserName());

        // 判断月日是否为空
        if(dkCheckInRecordDTO.getStrMonth() != null){
            data.setDateTime(formatDate(dkCheckInRecordDTO.getStrMonth()));
        }
        if(dkCheckInRecordDTO.getStrDay() != null){
            data.setDateTime(convertToChineseFormat(dkCheckInRecordDTO.getStrDay()));
        }

        // 定义集合，用于存储每天打卡记录
        List<DayRecord> dayRecords = new ArrayList<>();

        // 根据用户的ID查询该用户所有的打卡记录
        LambdaQueryWrapper<DkCheckInRecord> queryWrapper = buildQueryWrapper(dkCheckInRecordDTO, null);
        List<DkCheckInRecordDTO> dkCheckInRecordDTOS = dkMapper.selectVoList(queryWrapper);
        // 构造excel数据
        for(DkCheckInRecordDTO dk : dkCheckInRecordDTOS){
            // 根据打卡时间获取打卡日期
            LocalDate localDate = dk.getCheckInTime() != null ? dk.getCheckInTime().toLocalDate() : LocalDate.now();
            // 构造DayRecord
            DayRecord dayRecord = new DayRecord();

            //上班打卡
            dayRecord.setStartTime(null != dk.getClockIn() ? dk.getClockIn().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
            //下班打卡
            dayRecord.setEndTime(null != dk.getClockOut() ? dk.getClockOut().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
            dayRecord.setDay(dayRecord.getStartTime()==""?0:localDate.getDayOfMonth());
            dayRecords.add(dayRecord);
        }

        data.setDayRecords(dayRecords);
        return data;
    }
    //日本excel 整体信息赋值
    private void fillTemplateRiBen(Sheet sheet, EmployeeAttendance data) {
        // 1.填充标题区域
        setCellValue(sheet, 3, 1, data.getDateTime());
        setCellValue(sheet, 6, 6, data.getUserName());
        setCellValue(sheet, 6, 8, data.getEmployeeName());

        //
        // 要生成的年份
        int year = LocalDate.now().getYear();
        int month = LocalDate.now().getMonthValue();
        int rowIndex = 10;
        Map<Integer, List<CalendarGenerator.DayInfo>> calendar = CalendarGenerator.generateYearCalendar(year);
        List<CalendarGenerator.DayInfo> dayInfos = calendar.get(month);
        for (int i = 0; i < dayInfos.size(); i++) {
            rowIndex = i + 10;
            //初始化天数
            setCellValue(sheet, rowIndex, 1, dayInfos.get(i).getDay());
            //初始化星期 日本的星期名
            int week = dayInfos.get(i).getDayOfWeek().getValue();
            String weekName = getJpWeekName(week);
            setCellValue(sheet, rowIndex, 2, weekName);
            // 日本的星期六和星期日背景颜色设置
            if ("土".equals(weekName) || "日".equals(weekName)) {
                Row row = sheet.getRow(rowIndex);
                if (row == null) row = sheet.createRow(rowIndex);
                Cell cell = row.getCell(2);
                if (cell == null) {
                    cell = row.createCell(2);
                }
                Workbook workbook = sheet.getWorkbook();
                CellStyle style = workbook.createCellStyle();
                style.cloneStyleFrom(cell.getCellStyle()); // 保留原有样式
                style.setFillForegroundColor(IndexedColors.RED.getIndex());
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                cell.setCellStyle(style);
            }
        }

        Double hj = null;
        //考勤信息区域
        for (DayRecord record : data.getDayRecords()) {
            if(record.getDay() >0 &&record.getDay()<=31){
                Double half = fillTemplateRiBenCell(sheet, record.getDay()+9, record);
                //合计计算一共多少工时
                if(half!=null) {
                    if (hj!=null) {
                        hj = hj + half ;
                    } else {
                        hj = half;
                    }
                }
            }
        }
        //合计区域
        setCellValue(sheet, 41, 7, hj==null?"":hj);

    }
    //日本excel 打卡信息赋值
    private Double fillTemplateRiBenCell(Sheet sheet, int rowIndex, DayRecord record) {
        //1. 备注
        setCellValue(sheet, rowIndex, 8, record.getRemark());

        String startTime = record.getStartTime();
        String endTime = record.getEndTime();
        //2. 计算差值
        Double half = null;
        if (StringUtils.isNotBlank(startTime)&&StringUtils.isNotBlank(endTime)) {
            half = getHalfHourDiffAsCleanString(startTime, endTime);
            setCellValue(sheet, rowIndex, 7, half);
        } else {
            setCellValue(sheet, rowIndex, 7, "");
        }

        //3.上班打卡 、下班打卡
        if (StringUtils.isNotBlank(startTime)) {
            startTime = startTime.substring(11);
        }
        if (StringUtils.isNotBlank(endTime)) {
            endTime = endTime.substring(11);
        }
        setCellValue(sheet, rowIndex, 3, startTime);
        setCellValue(sheet, rowIndex, 4, endTime);

        return half;

    }
    //查询日本星期名字
    private String getJpWeekName(int week) {
        String WeekName = "";
        if(week == Constans.EXPORT_ZHOUYI){
            WeekName = "月";
        }else if(week == Constans.EXPORT_ZHOUER){
            WeekName = "火";
        }else if(week == Constans.EXPORT_ZHOUSAN){
            WeekName = "水";
        }else if(week == Constans.EXPORT_ZHOUSI){
            WeekName = "木";
        }else if(week == Constans.EXPORT_ZHOUWU){
            WeekName = "金";
        } else if(week == Constans.EXPORT_ZHOULIU){
            WeekName = "土";
        }else if(week == Constans.EXPORT_ZHOURI){
            WeekName = "日";
        }
        return WeekName;
    }

    /**
     * 计算加班时间，返回格式为 HH:mm:ss。如果加班时间为0则返回空字符串。
     * @param start 开始时间
     * @param end 结束时间
     * @param baseWorkHours 标准工作时长（比如 9.5）
     * @return 加班时长，格式为 "1:30:00"，若无加班则返回 ""
     */
    public static double calculateOvertime(LocalDateTime start, LocalDateTime end, double baseWorkHours) {
        // 计算时间差（分钟）
        long minutes = Duration.between(start, end).toMinutes();

        // 转换为小时（带小数）
        double totalHours = minutes / 60.0;

        // 减去标准工时  小时
        double overtime = totalHours - baseWorkHours;

        // 如果没超出，直接返回 0
        if (overtime <= 0) {
            return 0d;
        }
        double floored = Math.floor(overtime * 2) / 2.0;
        return floored;
    }
    public static String formatOvertime(double Overtime) {
        if (Overtime==0) {
            return "";
        }
        // 拆分小时和分钟部分
        int hours = (int) Overtime;
        int minutesPart = (Overtime % 1 == 0.5) ? 30 : 0;

        // 格式化为 HH:mm:ss 字符串
        return String.format("%d:%02d:00", hours, minutesPart);
    }








    //为excel row的各个cell赋值
    private void setCellValue(Sheet sheet, int rowIndex, int colIndex, Object value) {
        Row row = sheet.getRow(rowIndex);
        if (row == null) {
            row = sheet.createRow(rowIndex);
        }

        Cell cell = row.getCell(colIndex);
        if (cell == null) {
            cell = row.createCell(colIndex);
        }

        if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Integer) {
            cell.setCellValue((Integer) value);
        } else if (value instanceof Double) {
            cell.setCellValue((Double) value);
        } else if (value != null) {
            cell.setCellValue(value.toString());
        }
    }

    public static String convertToChineseFormat(String dateStr) {
        // 解析输入字符串为LocalDate
        LocalDate date = LocalDate.parse(dateStr);

        // 定义目标格式（年-月-日带前导零）
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");

        // 格式化日期
        return date.format(formatter);
    }

    public static String formatDate(String input) {
        // 解析输入字符串为LocalDate
        LocalDate date = LocalDate.parse(input + "-01");  // 假设输入是年月，补全为月初

        // 定义目标格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月");

        // 格式化日期
        return date.format(formatter);
    }

}
