package com.sundot.airport.web.controller.exam;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.sundot.airport.common.annotation.Log;
import com.sundot.airport.common.core.controller.BaseController;
import com.sundot.airport.common.core.domain.AjaxResult;
import com.sundot.airport.common.core.domain.entity.SysUser;
import com.sundot.airport.common.core.page.TableDataInfo;
import com.sundot.airport.common.enums.BusinessType;
import com.sundot.airport.common.exception.ServiceException;
import com.sundot.airport.common.utils.poi.ExcelUtil;
import com.sundot.airport.exam.domain.ExamMonthlyScore;
import com.sundot.airport.exam.dto.ExamMonthlyScoreImportVO;
import com.sundot.airport.exam.service.IExamMonthlyScoreService;
import com.sundot.airport.system.service.ISysUserService;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 月考成绩Controller
 *
 * @author ruoyi
 * @date 2026-05-06
 */
@RestController
@RequestMapping("/exam/monthlyScore")
public class ExamMonthlyScoreController extends BaseController {
    @Autowired
    private IExamMonthlyScoreService examMonthlyScoreService;

    @Autowired
    private ISysUserService userService;

    /**
     * 查询月考成绩列表
     */
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:list')")
    @GetMapping("/list")
    public TableDataInfo list(ExamMonthlyScore examMonthlyScore) {
        startPage();
        List<ExamMonthlyScore> list = examMonthlyScoreService.selectExamMonthlyScoreList(examMonthlyScore);
        return getDataTable(list);
    }

    /**
     * 导出月考成绩列表
     */
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:export')")
    @Log(title = "月考成绩", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ExamMonthlyScore examMonthlyScore) {
        List<ExamMonthlyScore> list = examMonthlyScoreService.selectExamMonthlyScoreList(examMonthlyScore);
        ExcelUtil<ExamMonthlyScore> util = new ExcelUtil<ExamMonthlyScore>(ExamMonthlyScore.class);
        util.exportExcel(response, list, "月考成绩数据");
    }

    /**
     * 获取月考成绩详细信息
     */
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(examMonthlyScoreService.selectExamMonthlyScoreById(id));
    }

    /**
     * 新增月考成绩
     */
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:add')")
    @Log(title = "月考成绩", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ExamMonthlyScore examMonthlyScore) {
        return toAjax(examMonthlyScoreService.insertExamMonthlyScore(examMonthlyScore));
    }

    /**
     * 修改月考成绩
     */
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:edit')")
    @Log(title = "月考成绩", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ExamMonthlyScore examMonthlyScore) {
        return toAjax(examMonthlyScoreService.updateExamMonthlyScore(examMonthlyScore));
    }

    /**
     * 删除月考成绩
     */
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:remove')")
    @Log(title = "月考成绩", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(examMonthlyScoreService.deleteExamMonthlyScoreByIds(ids));
    }

    /**
     * 下载导入模板
     */
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<ExamMonthlyScoreImportVO> util = new ExcelUtil<ExamMonthlyScoreImportVO>(ExamMonthlyScoreImportVO.class);
        util.importTemplateExcel(response, "月考成绩数据");
    }

    /**
     * 导入月考成绩数据
     */
    @Log(title = "月考成绩", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('exam:monthlyScore:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<ExamMonthlyScoreImportVO> util = new ExcelUtil<ExamMonthlyScoreImportVO>(ExamMonthlyScoreImportVO.class);
        List<ExamMonthlyScoreImportVO> list = util.importExcel(file.getInputStream());
        if (CollectionUtil.isEmpty(list)) {
            throw new ServiceException("导入月考成绩数据不能为空");
        }
        String message = importData(list, updateSupport);
        return success(message);
    }

    /**
     * 导入数据处理
     */
    private String importData(List<ExamMonthlyScoreImportVO> list, boolean updateSupport) {
        if (CollectionUtil.isEmpty(list)) {
            throw new ServiceException("导入月考成绩数据不能为空！");
        }

        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        // 1. 预处理：提取所有学生姓名，批量查询用户
        List<String> studentNames = list.stream()
                .map(ExamMonthlyScoreImportVO::getStudentName)
                .filter(StrUtil::isNotBlank)
                .distinct()
                .collect(java.util.stream.Collectors.toList());

        // 批量查询用户（同时按用户名和昵称查询）
        java.util.Map<String, SysUser> userMap = new java.util.HashMap<>();
        if (CollectionUtil.isNotEmpty(studentNames)) {
            List<SysUser> users = userService.selectUsersByNames(studentNames);
            for (SysUser user : users) {
                // 优先用用户名做key，如果没有则用昵称
                if (StrUtil.isNotBlank(user.getUserName())) {
                    userMap.put(user.getUserName(), user);
                }
                if (StrUtil.isNotBlank(user.getNickName())) {
                    userMap.put(user.getNickName(), user);
                }
            }
        }

        List<Long> userIds = userMap.values().stream()
                .map(SysUser::getUserId)
                .distinct()
                .collect(java.util.stream.Collectors.toList());

        java.util.Map<String, ExamMonthlyScore> existScoreMap = new java.util.HashMap<>();
        if (CollectionUtil.isNotEmpty(userIds)) {
            // 批量查询这些用户的月考成绩
            List<ExamMonthlyScore> allScores = examMonthlyScoreService.selectByUserIds(userIds);
            for (ExamMonthlyScore score : allScores) {
                String key = score.getUserId() + "_" + score.getYearMonth();
                existScoreMap.put(key, score);
            }
        }

        List<ExamMonthlyScore> insertList = new java.util.ArrayList<>();
        List<ExamMonthlyScore> updateList = new java.util.ArrayList<>();

        for (int i = 0; i < list.size(); i++) {
            ExamMonthlyScoreImportVO vo = list.get(i);
            int rowNum = i + 2;

            try {
                // 判断是否为空行（所有字段都为空）
                if (isEmptyRow(vo)) {
                    continue; // 跳过空行
                }

                // 验证必填字段
                if (StrUtil.isBlank(vo.getStudentName())) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、第").append(rowNum).append("行：学生姓名不能为空");
                    continue;
                }

                if (StrUtil.isBlank(vo.getYearMonth())) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、第").append(rowNum).append("行：年月不能为空");
                    continue;
                }

                // 从缓存中获取用户
                SysUser user = userMap.get(vo.getStudentName());
                if (user == null) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、第").append(rowNum).append("行：用户【").append(vo.getStudentName()).append("】不存在");
                    continue;
                }

                // 转换年月格式为 yyyy-MM
                String yearMonth = formatYearMonth(vo.getYearMonth());

                // 从缓存中检查是否已存在
                String key = user.getUserId() + "_" + yearMonth;
                ExamMonthlyScore existScore = existScoreMap.get(key);

                ExamMonthlyScore score = new ExamMonthlyScore();
                score.setUserId(user.getUserId());
                score.setStudentName(vo.getStudentName());
                score.setYearMonth(yearMonth);
                score.setTeam(vo.getTeam());
                score.setJobPosition(vo.getJobPosition());
                score.setComprehensiveScore(vo.getComprehensiveScore());
                score.setComprehensiveTime(vo.getComprehensiveTime());
                score.setSpecialScore(vo.getSpecialScore());
                score.setSpecialTime(vo.getSpecialTime());

                if (existScore != null) {
                    // 已存在
                    if (updateSupport) {
                        score.setId(existScore.getId());
                        score.setUpdateBy(getLoginUser().getUsername());
                        updateList.add(score);
                        successNum++;
                        successMsg.append("<br/>").append(successNum).append("、用户【").append(vo.getStudentName()).append("】").append(yearMonth).append(" 月考成绩更新成功");
                    } else {
                        failureNum++;
                        failureMsg.append("<br/>").append(failureNum).append("、第").append(rowNum).append("行：用户【").append(vo.getStudentName()).append("】").append(yearMonth).append(" 月考成绩已存在");
                    }
                } else {
                    // 新增
                    score.setCreateBy(getLoginUser().getUsername());
                    insertList.add(score);
                    successNum++;
                    successMsg.append("<br/>").append(successNum).append("、用户【").append(vo.getStudentName()).append("】").append(yearMonth).append(" 月考成绩导入成功");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、第" + rowNum + "行：导入失败：";
                failureMsg.append(msg).append(e.getMessage());
            }
        }

        // 4. 批量插入和更新
        if (CollectionUtil.isNotEmpty(insertList)) {
            for (ExamMonthlyScore score : insertList) {
                examMonthlyScoreService.insertExamMonthlyScore(score);
            }
        }
        if (CollectionUtil.isNotEmpty(updateList)) {
            for (ExamMonthlyScore score : updateList) {
                examMonthlyScoreService.updateExamMonthlyScore(score);
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 判断是否为空行（所有字段都为空）
     */
    private boolean isEmptyRow(ExamMonthlyScoreImportVO vo) {
        return StrUtil.isBlank(vo.getYearMonth())
                && StrUtil.isBlank(vo.getStudentName())
                && StrUtil.isBlank(vo.getTeam())
                && StrUtil.isBlank(vo.getJobPosition())
                && vo.getComprehensiveScore() == null
                && StrUtil.isBlank(vo.getComprehensiveTime())
                && vo.getSpecialScore() == null
                && StrUtil.isBlank(vo.getSpecialTime());
    }

    /**
     * 格式化年月为 yyyy-MM 格式（支持多种输入格式）
     */
    private String formatYearMonth(String yearMonth) {
        if (StrUtil.isBlank(yearMonth)) {
            return yearMonth;
        }

        yearMonth = yearMonth.trim();

        // 1. 尝试解析为数字（Excel日期序列号，如46082）
        try {
            double serialNumber = Double.parseDouble(yearMonth);
            if (serialNumber > 1000 && serialNumber < 100000) {
                Date date = DateUtil.getJavaDate(serialNumber);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                return sdf.format(date);
            }
        } catch (NumberFormatException e) {
            // 不是数字，继续其他解析方式
        }

        // 2. 处理中文格式：2026年3月、2026年03月等
        if (yearMonth.contains("年") && yearMonth.contains("月")) {
            yearMonth = yearMonth.replace("年", "-").replace("月", "");
        }

        // 3. 处理点号分隔：2026.03、2026.3等
        if (yearMonth.contains(".")) {
            yearMonth = yearMonth.replace(".", "-");
        }

        // 4. 处理斜杠分隔：2026/03、2026/3等
        if (yearMonth.contains("/")) {
            yearMonth = yearMonth.replace("/", "-");
        }

        // 5. 标准化月份格式
        String[] parts = yearMonth.split("-");
        if (parts.length >= 2) {
            String year = parts[0].trim();
            String month = parts[1].trim();

            // 验证年份和月份是否为有效数字
            if (year.matches("\\d{4}") && month.matches("\\d{1,2}")) {
                int monthNum = Integer.parseInt(month);
                if (monthNum >= 1 && monthNum <= 12) {
                    // 格式化月份为两位数
                    String formattedMonth = String.format("%02d", monthNum);
                    return year + "-" + formattedMonth;
                }
            }
        }

        // 如果无法解析，返回原始值
        return yearMonth;
    }
}
