package com.bonus.system.att.controller;

import com.bonus.common.core.utils.DateTimeHelper;
import com.bonus.common.core.utils.StringHelper;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.utils.poi.MultiSheetExcelExporter;
import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.web.page.TableDataInfo;
import com.bonus.common.log.annotation.Log;
import com.bonus.common.log.annotation.SysLog;
import com.bonus.common.log.enums.BusinessType;
import com.bonus.common.log.enums.OperaType;
import com.bonus.common.security.annotation.RequiresPermissions;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.system.api.domain.MapVo;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.att.entity.*;
import com.bonus.system.att.service.AttDetailByMonthService;
import com.bonus.system.att.service.AttGroupService;
import com.bonus.system.att.service.AttendanceDetailsService;
import com.bonus.system.basic.dao.SysOrgDao;
import com.bonus.system.dept.dao.ProDeptRoleDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;

/**
 * 月异常报表
 *
 * @author hongchao
 */
@RestController
@RequestMapping("/attDetailByMonth")
@Slf4j
public class AttDetailByMonthController extends BaseController {

    @Resource(name = "attDetailByMonthService")
    private AttDetailByMonthService attDetailByMonthService;

    @Resource(name = "ProDeptRoleDao")
    private ProDeptRoleDao proDeptRoleDao;

    @Resource
    private SysOrgDao sysOrgDao;

    @RequiresPermissions("att:detail:query")
    @GetMapping("/list")
    @Log(title = "考勤报表->月异常报表->列表查询", businessType = BusinessType.QUERY)
    public TableDataInfo list(AttDetailByMonthBean data) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<String> roleId = sysUser.getRoleList();
        //管理员与人资角色可以看到所有
        if (roleId != null && !roleId.isEmpty()) {
            if (Collections.frequency(roleId, "1") == 0 && Collections.frequency(roleId, "16") == 0) {
                // 根据用户id查询是否是管理员或帮忙负责人
                Long userId = SecurityUtils.getUserId();
                List<MapVo> orgList = sysOrgDao.getOrgIdList(userId);
                if (!orgList.isEmpty()) {
                    // 使用 LinkedHashSet 来保证顺序并自动去重
                    Set<String> idsSet = new LinkedHashSet<>();
                    for (MapVo mapVo : orgList) {
                        String id = proDeptRoleDao.getOrgChildById(mapVo.getId());
                        if (id != null && !id.trim().isEmpty()) { // 防止空或仅含空白字符的字符串
                            // 将分割后的数组添加到 Set 中，自动去重
                            Collections.addAll(idsSet, id.split(","));
                        }
                    }
                    // 如果需要转换回 List 类型
                    List<String> uniqueIds = new ArrayList<>(idsSet);
                    data.setOrgList(uniqueIds);
                } else {
                    data.setUserId(userId);
                }
            }
        }
        startPage();
        List<AttDetailByMonthBean> list = attDetailByMonthService.selectAttDetailList(data);
        return getDataTable(list);
    }

    /**
     * 根据用户id获取打卡详细信息
     */
    @RequiresPermissions("att:detail:query")
    @GetMapping(value = "/getDetail")
    public TableDataInfo getDetail(AttDetailBean data) {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<String> roleId = sysUser.getRoleList();
        //管理员与人资角色可以看到所有
        if (roleId != null && !roleId.isEmpty()) {
            if (Collections.frequency(roleId, "1") == 0 && Collections.frequency(roleId, "16") == 0) {
                List<MapVo> orgList = sysUser.getOrgList();
                if (!orgList.isEmpty()) {
                    ArrayList<String> ids = new ArrayList<>();
                    for (MapVo mapVo : orgList) {
                        String id = proDeptRoleDao.getOrgChildById(mapVo.getId());
                        // 使用 Arrays.asList() 将数组转换为 ArrayList
                        ArrayList<String> idList = new ArrayList<>(Arrays.asList(id.split(",")));
                        ids.addAll(idList);
//                        ids.add(String.valueOf(mapVo.getId()));
                    }
                    data.setOrgList(ids);
                }
            }
        }
        startPage();
        List<AttDetailBean> list = attDetailByMonthService.getDetailList(data);
        return getDataTable(list);
    }

    /**
     * 根据用户id获取请假详细信息
     */
    @RequiresPermissions("att:detail:query")
    @GetMapping(value = "/getDetailLeave")
    public TableDataInfo getDetailLeave(@RequestBody AttDetailLeaveBean data) {
        startPage();
        List<AttDetailLeaveBean> list = attDetailByMonthService.getDetailLeaveList(data);
        return getDataTable(list);
    }


    /**
     * 考勤明细导出
     */
    @Resource(name = "attendanceDetailsService")
    private AttendanceDetailsService attendanceDetailsService;

    @RequiresPermissions("att:detail:export")
    @GetMapping("/export")
    public void export(HttpServletResponse response, AttDetailByMonthBean bean) {
        try {
            SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
            List<String> roleId = sysUser.getRoleList();
            //管理员与人资角色可以看到所有
            if (roleId != null && !roleId.isEmpty()) {
                if (Collections.frequency(roleId, "1") == 0 && Collections.frequency(roleId, "16") == 0) {
                    // 根据用户id查询是否是管理员或帮忙负责人
                    Long userId = SecurityUtils.getUserId();
                    List<MapVo> orgList = sysOrgDao.getOrgIdList(userId);
                    if (!orgList.isEmpty()) {
                        // 使用 LinkedHashSet 来保证顺序并自动去重
                        Set<String> idsSet = new LinkedHashSet<>();
                        for (MapVo mapVo : orgList) {
                            String id = proDeptRoleDao.getOrgChildById(mapVo.getId());
                            if (id != null && !id.trim().isEmpty()) { // 防止空或仅含空白字符的字符串
                                // 将分割后的数组添加到 Set 中，自动去重
                                Collections.addAll(idsSet, id.split(","));
                            }
                        }
                        // 如果需要转换回 List 类型
                        List<String> uniqueIds = new ArrayList<>(idsSet);
                        bean.setOrgList(uniqueIds);
                    } else {
                        bean.setUserId(userId);
                    }
                }
            }
            MultiSheetExcelExporter exporter = new MultiSheetExcelExporter();
            //将表格时间区间取出来做标题
            String title = bean.getStartMonth() + " ~ " + bean.getEndMonth();
            List<AttDetailByMonthBean> attDayReportList = attDetailByMonthService.selectAttDetailList(bean);
            Sheet departmentSheet1 = exporter.createSheet("月异常报表详情");
            List<String> departmentHeaders1 = Arrays.asList("序号", "姓名", "所属部门", "考勤月","打卡记录", "应考勤天数", "正常打卡天数",
                    "迟到天数", "早退天数", "旷工天数", "打卡地异常天数", "出入异常天数");
            exporter.addHeaderRowAndTitle(departmentSheet1, departmentHeaders1, title);
            List<Map<String, Object>> departmentData1 = new ArrayList<>();
            for (int i = 0; i < attDayReportList.size(); i++) {
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("序号", i + 1);
                map.put("姓名", attDayReportList.get(i).getName());
                map.put("所属部门", attDayReportList.get(i).getOrgName());
                map.put("考勤月", attDayReportList.get(i).getAttCurrentMonth());
                map.put("打卡记录", attDayReportList.get(i).getClockingRecordNum());
                map.put("应考勤天数", attDayReportList.get(i).getRequiredDays());
                map.put("正常打卡天数", attDayReportList.get(i).getNormalNum());
                map.put("迟到天数", attDayReportList.get(i).getLateNum());
                map.put("早退天数", attDayReportList.get(i).getEarlyNum());
                map.put("旷工天数", attDayReportList.get(i).getSkippingNum());
                map.put("打卡地异常天数", attDayReportList.get(i).getAddressErrorNum());
                map.put("出入异常天数", attDayReportList.get(i).getEinErrorNum());
                departmentData1.add(map);
            }
            exporter.addDataRows(departmentSheet1, departmentData1, departmentHeaders1);
            //详情的数据导出
            Map<String, String> headers = new HashMap<>();
            headers.put("1", "正常打卡");
            headers.put("2", "迟到详情");
            headers.put("3", "旷工详情");
            headers.put("4", "早退详情");
            headers.put("5", "轮休详情");
            headers.put("6", "请假详情");
            headers.put("7", "临时外出");
            headers.put("8", "出入异常");
            headers.put("9", "打卡地异常");
            headers.put("99", "工作外出");
            Map<String, String> attStatus = getStringStringMap();
            if (StringHelper.isNotEmpty(bean.getStartMonth()) && StringHelper.isNotEmpty(bean.getEndMonth())) {
//                List<String> monthFirstAndLast = getMonthFirstAndLast(bean.getAttCurrentMonth());
                List<String> monthFirstAndLast = DateTimeHelper.getMonthStartAndEndDay(bean.getStartMonth(),bean.getEndMonth());
                AttDetailBean dayTable = new AttDetailBean();
                dayTable.setStartDate(monthFirstAndLast.get(0));
                dayTable.setEndDate(monthFirstAndLast.get(1));
                dayTable.setName(bean.getName());
                if (bean.getOrgId() != null) {
                    dayTable.setOrgId(String.valueOf(bean.getOrgId()));
                } else {
                    //受限于当前登录人
                    if (bean.getOrgList() != null && !bean.getOrgList().isEmpty()) {
                        dayTable.setOrgList(bean.getOrgList());
                    }
                }
                headers.entrySet()
                        .forEach(entry -> {
                            if ("99".equals(entry.getKey())) {
                                AttDataDetailsBean att = new AttDataDetailsBean();
                                att.setStartDate(monthFirstAndLast.get(0));
                                att.setEndDate(monthFirstAndLast.get(1));
//                                att.setAttCurrentMonth(bean.getAttCurrentMonth());
                                if (bean.getOrgId() != null) {
                                    att.setOrgId(Long.valueOf(bean.getOrgId()));
                                } else {
                                    //受限于当前登录人
                                    if (bean.getOrgList() != null && !bean.getOrgList().isEmpty()) {
                                        att.setOrgList(bean.getOrgList());
                                    }
                                }
                                att.setUserName(bean.getName());
                                //存在人员换组织情况，先查人再去查工作外出
                                List<AttDataDetailsBean> list = attendanceDetailsService.getOrgUserOutCountList(att);
                                Sheet departmentSheet2 = exporter.createSheet(entry.getValue());
                                List<String> departmentHeaders2 = Arrays.asList("序号", "考勤日期", "姓名", "所属部门", "打卡时间", "打卡地址");
                                exporter.addHeaderRowAndTitle(departmentSheet2, departmentHeaders2, title);
                                List<Map<String, Object>> departmentData2 = new ArrayList<>();
                                for (int i = 0; i < list.size(); i++) {
                                    Map<String, Object> map = new LinkedHashMap<>();
                                    map.put("序号", i + 1);
                                    map.put("考勤日期", list.get(i).getAttCurrentDay());
                                    map.put("姓名", list.get(i).getUserName());
                                    map.put("所属部门", list.get(i).getOrgName());
                                    map.put("打卡时间", list.get(i).getAttCurrentTime());
                                    map.put("打卡地址", list.get(i).getAttAddress());
                                    departmentData2.add(map);
                                    departmentData2.add(map);
                                }
                                exporter.addDataRows(departmentSheet2, departmentData2, departmentHeaders2);
                            } else {
                                dayTable.setAttStatis(Integer.parseInt(entry.getKey()));
                                List<AttDetailBean> list = attDetailByMonthService.getDetailList(dayTable);
                                Sheet departmentSheet2 = exporter.createSheet(entry.getValue());
                                List<String> departmentHeaders2 = Arrays.asList("序号", "姓名", "所属部门", "考勤日期", "上班打卡时间", "上班状态", "打卡地址", "下班打卡时间", "下班状态", "打卡地址");
                                exporter.addHeaderRowAndTitle(departmentSheet2, departmentHeaders2, title);
                                List<Map<String, Object>> departmentData2 = new ArrayList<>();
                                for (int i = 0; i < list.size(); i++) {
                                    Map<String, Object> map = new LinkedHashMap<>();
                                    map.put("序号", i + 1);
                                    map.put("姓名", list.get(i).getName());
                                    map.put("所属部门", list.get(i).getOrgName());
                                    map.put("考勤日期", list.get(i).getAttCurrent());
                                    map.put("上班打卡时间", list.get(i).getGoWorkTime());
                                    map.put("上班状态", attStatus.get(String.valueOf(list.get(i).getGoWorkStatus())));
                                    map.put("上班打卡地址", list.get(i).getOffWorkAddress());
                                    map.put("下班打卡时间", list.get(i).getOffWorkTime());
                                    map.put("下班状态", attStatus.get(String.valueOf(list.get(i).getOffWorkStatus())));
                                    map.put("下班打卡地址", list.get(i).getOffWorkAddress());
                                    departmentData2.add(map);
                                }
                                exporter.addDataRows(departmentSheet2, departmentData2, departmentHeaders2);
                            }
                        });
                // 导出Excel文件
                exporter.exportToResponse(response, "月报表导出");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private List<String> getMonthFirstAndLast(String monthString) {
        List<String> months = new ArrayList<>();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        YearMonth yearMonth;
        // 使用预定义的 ISO_LOCAL_DATE 格式 (yyyy-MM-dd)
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE;

        try {
            // 判空及默认为当月
            if (monthString == null || monthString.trim().isEmpty()) {
                // 如果字符串为空或仅包含空白字符，取当前月份
                yearMonth = YearMonth.from(LocalDate.now());
            } else {
                // 尝试将字符串解析为 YearMonth 对象
                yearMonth = YearMonth.parse(monthString, formatter);
            }
            // 获取该月的第一天
            LocalDate firstDayOfMonth = yearMonth.atDay(1);
            // 获取该月的最后一天
            LocalDate lastDayOfMonth = yearMonth.atEndOfMonth();
            months.add(firstDayOfMonth.format(isoFormatter));
            months.add(lastDayOfMonth.format(isoFormatter));
        } catch (DateTimeParseException e) {
            // 如果解析失败，打印错误信息并使用当前月份
            YearMonth currentYearMonth = YearMonth.from(LocalDate.now());
            LocalDate firstDayOfCurrentMonth = currentYearMonth.atDay(1);
            LocalDate lastDayOfCurrentMonth = currentYearMonth.atEndOfMonth();
            months.add(firstDayOfCurrentMonth.format(isoFormatter));
            months.add(lastDayOfCurrentMonth.format(isoFormatter));
        }
        return months;
    }

    private Map<String, String> getStringStringMap() {
        Map<String, String> attStatus = new HashMap<>();
        attStatus.put("1", "正常");
        attStatus.put("2", "迟到");
        attStatus.put("3", "旷工");
        attStatus.put("4", "早退");
        attStatus.put("5", "轮休");
        attStatus.put("6", "请假");
        attStatus.put("7", "外出");
        attStatus.put("8", "出入异常");
        attStatus.put("9", "打卡地异常");
        attStatus.put("10", "出差");
        attStatus.put("11", "法定节假日");
        attStatus.put("12", "年休假");
        attStatus.put("13", "探亲假");
        attStatus.put("14", "事假");
        attStatus.put("15", "病假");
        attStatus.put("16", "产假");
        attStatus.put("17", "婚假");
        attStatus.put("18", "丧假");
        attStatus.put("19", "育儿假");
        attStatus.put("20", "陪护假");
        return attStatus;
    }

}
