package com.xhkjedu.smarking.utils;

import com.xhkjedu.smarking.model.stupaper.MsPaperStudentScore;
import com.xhkjedu.smarking.vo.exam.ESubjectVo;
import com.xhkjedu.smarking.vo.stupaper.PaperStuScoreVo;
import com.xhkjedu.utils.N_Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 * @Description:导入
 * @Author: WN
 * @Date: 2024/11/13 11:31:52
 **/
@Component
@Slf4j
public class ImportUtil {
    //2003- 版本的excel
    private final static String excel2003L = ".xls";
    //2007+ 版本的excel
    private final static String excel2007U = ".xlsx";


    public static List<MsPaperStudentScore> readExcelStudentScore(MultipartFile file, Map<String,ESubjectVo> subjectMap,Map<String,PaperStuScoreVo> stuMap,List<String> classNames,Integer createid) throws Exception {
        List<MsPaperStudentScore> rtnList = new ArrayList<>();//需要保存的学生分数
        Integer timestamp = N_Utils.getSecondTimestamp();

        try {
            // 数据校验
            isExcelEmpty(file);
            InputStream in = file.getInputStream();
            String fileName = file.getOriginalFilename();
            Workbook work = getWorkbook(in, fileName);
            //遍历所有sheet
            for (int i = 0; i < work.getNumberOfSheets(); i++) {
                Sheet sheet = work.getSheetAt(i);
                int rows = sheet.getLastRowNum(); // 获取最后一个实际行的下标，比行数小1
                String sheetName = sheet.getSheetName();//根据sheet名称获取科目信息
                //获取科目信息
                if(!subjectMap.containsKey(sheetName)) throw new Exception("科目信息不存在");

                ESubjectVo subject = subjectMap.get(sheetName);//sheet对应科目信息

                int firstRowNum = sheet.getFirstRowNum(); // 获取第一个实际行的下标，（firstRowNum=0）
                Row row = sheet.getRow(firstRowNum);//标题行
                String titleName = "姓名性别班级准考证号补录成绩";//标题格式
                StringBuilder sb = new StringBuilder();
                sb.append(row.getCell(0));//姓名
                sb.append(row.getCell(1));//性别
                sb.append(row.getCell(2));//班级
                sb.append(row.getCell(3));//准考证号
                sb.append(row.getCell(4));//补录成绩
                String importTitleName = sb.toString().replaceAll(" |（必填）", "");
                if(!titleName.equals(importTitleName)) throw new Exception("标题格式不正确");

                Map<String, String> nameMap = new HashMap<>();

                /*
                 * 遍历当前sheet中的所有行
                 * 排除第一行  第一行为标题头 不纳入遍历
                 */
                for (int x = firstRowNum + 1; x <= rows; x++) {
                    // 获取行
                    row = sheet.getRow(x);
                    if (row == null) {//若此行为空，则跳出循环继续下一行
                        continue;
                    } else if (isEmptyCell(row.getCell(0)) && isEmptyCell(row.getCell(1))) {
                        continue;
                    }
                    PaperStuScoreVo stu = new PaperStuScoreVo();// 每一行一个学生信息
                    int firstCellNum = row.getFirstCellNum();// 每一行的第一列，（firstCellNum=0）
                    if (firstCellNum == 1) throw new Exception("第" + (x + 1) + "行姓名不能为空");
                    int lastCellNum = row.getLastCellNum();// 每一行的最后一列，获取列数，比最后一列列标大1
                    //遍历所有的列
                    for (int y = firstCellNum; y < lastCellNum; y++) {
                        Cell cell = row.getCell(y);
                        if (y == 0) {   // 姓名
                            if (isEmptyCell(cell)) {
                                throw new Exception("第" + (x + 1) + "行姓名不能为空");
                            } else {
                                stu.setStudentname(getCellValue(cell));
                            }
                        } else if (y == 1) {//性别
                            if (isEmptyCell(cell)) {
                                stu.setUsersex(0);
                            } else {
                                String usersex = getCellValue(cell);
                                if (usersex.equals("女")) {
                                    stu.setUsersex(2);
                                } else if (usersex.equals("男")) {
                                    stu.setUsersex(1);
                                } else {
                                    stu.setUsersex(0);
                                }
                            }
                        } else if (y == 2) {//班级
                            if (isEmptyCell(cell)) {
                                throw new Exception("第" + (x + 1) + "行班级不能为空");
                            } else {
                                String classname = getCellValue(cell);
                                if(!classNames.contains(classname)){
                                    throw new Exception("第" + (x + 1) + "行班级不存在");
                                }else{
                                    stu.setClassname(classname);
                                }
                            }
                        } else if (y == 3) {//准考证号
                            if (isEmptyCell(cell)) {
                                throw new Exception("第" + (x + 1) + "行准考证号不能为空");
                            } else {
                                String examno = getCellValue(cell);
                                if(!stuMap.containsKey(examno)) {
                                    throw new Exception("第" + (x + 1) + "行准考证号不存在");
                                }else{
                                    stu.setExamno(examno);
                                }

                            }
                        } else if (y == 4) {//补录成绩
                            String fillScore = getCellValue(cell);
                            if(N_Utils.isEmpty(fillScore)){
                                stu.setStuscore(null);
                            }else{
                                stu.setStuscore(Double.parseDouble(fillScore));
                            }
                        }
                    }
                    //判断学生信息对应用户是否存在
                    PaperStuScoreVo oldStu = stuMap.get(stu.getExamno());
                    if(stu.getStuscore() !=null && oldStu.getStuscoretype() != 1){
                        //说明设置了分数，则进行用户其他信息教研
                        if(!stu.getStudentname().equals(oldStu.getStudentname()) || !stu.getClassname().equals(oldStu.getClassname())){
                            throw new Exception("第" + (x + 1) + "行学生不存在或没有参加本次考试");
                        }else{
                            MsPaperStudentScore score = setPaperStudentScore(oldStu,subject.getSubjectid(),stu.getStuscore(),createid,timestamp);
                            rtnList.add(score);
                        }
                    }
                }
            }

        } catch (Exception e) {
            log.error("读取Excel文件失败", e.getMessage());
            throw new Exception("读取Excel文件失败");
        }
        return rtnList;
    }

    private static MsPaperStudentScore setPaperStudentScore(PaperStuScoreVo oldStu, String subjectid, double stuscore, Integer createid, Integer timestamp) {
        MsPaperStudentScore stuScore = new MsPaperStudentScore();
        stuScore.setExamid(oldStu.getExamid());
        stuScore.setMpid(oldStu.getMpid());
        stuScore.setSubjectid(subjectid);
        stuScore.setStudentid(oldStu.getStudentid());
        stuScore.setFillpre(oldStu.getStuscore());
        stuScore.setFillscore(stuscore);
        stuScore.setCreateid(createid);
        stuScore.setCreatetime(timestamp);
        return stuScore;
    }


    /**
     * 根据文件后缀，自适应上传文件的版本
     *
     * @return org.apache.poi.ss.usermodel.Workbook
     * @Param [inStr, fileName]
     * @Author ywx
     * @Date 2020/6/3 16:42
     **/
    public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
        Workbook wb;
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        if (excel2003L.equals(fileType)) {
            wb = new HSSFWorkbook(inStr);  //2003-
        } else if (excel2007U.equals(fileType)) {
            wb = new XSSFWorkbook(inStr);  //2007+
        } else {
            throw new Exception("Excel格式解析有误！");
        }
        return wb;
    }

    /**
     * 判断单元格是否是空值
     *
     * @return java.lang.Boolean
     * @Param [cell]
     * @Author ywx
     * @Date 2020/6/3 16:37
     **/
    public static Boolean isEmptyCell(Cell cell) {
        if (cell != null) {
            Boolean rtn = true;
            if (N_Utils.isNotEmpty(getCellValue(cell))) {
                rtn = false;
            }
            return rtn;
        } else {
            return true;
        }
    }

    /**
     * 对表格中数值进行格式化
     *
     * @return java.lang.Object
     * @Param [cell]
     * @Author ywx
     * @Date 2020/6/3 16:41
     **/
    public static String getCellValue(Cell cell) {
        String value = null;
        if (cell == null) return value;
        DecimalFormat df = new DecimalFormat("0");  //格式化number String字符
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  //日期格式化
        DecimalFormat df2 = new DecimalFormat("0");  //格式化数字
        switch (cell.getCellTypeEnum()) {
            case STRING:
                value = cell.getRichStringCellValue().getString();
                break;
            case NUMERIC:
                String cellStyle = cell.getCellStyle().getDataFormatString();
                if ("General".equals(cellStyle)) {
                    Double d = cell.getNumericCellValue();
                    if (d.toString().contains("E")) {
                        cell.setCellType(CellType.STRING);
                        value = cell.getStringCellValue();
                    } else {
                        value = df.format(d);
                    }
                } else if ("m/d/yy".equals(cellStyle)) {
                    value = sdf.format(cell.getDateCellValue());
                } else {
                    // 处理数字单元格，可能是整数或双精度浮点数
                    if (cell.getCellStyle().getDataFormat() == 0) {
                        // 假定没有特殊的数字格式，则处理为双精度浮点数
                        value = cell.getNumericCellValue()+"";
                    } else {
                        value = df2.format(cell.getNumericCellValue());
                    }
                }
                break;
            case BOOLEAN:
                boolean rtn = cell.getBooleanCellValue();
                if (rtn) {
                    value = "1";//真
                } else {
                    value = "0";//假
                }
                break;
            case BLANK:
                value = "";
                break;
            case FORMULA://读取excel公式的值
                try {
                    value = String.valueOf(cell.getNumericCellValue());
                } catch (IllegalStateException e) {
                    value = String.valueOf(cell.getRichStringCellValue());
                }
                break;
            default:
                break;
        }
        return N_Utils.strTrim(value);
    }

    /**
     * 检验Excel内容是否为空
     *
     * @return void
     * @Param [file]
     * @Author ywx
     * @Date 2020/6/3 16:36
     **/
    public static void isExcelEmpty(MultipartFile file) throws Exception {
        if (null == file || file.isEmpty()) {
            throw new Exception("文件不存在！");
        }
        InputStream in = file.getInputStream();
        String fileName = file.getOriginalFilename();
        Workbook work = getWorkbook(in, fileName);
        if (null == work) {
            throw new Exception("Excel内容为空！");
        }
        Integer sheet_size = work.getNumberOfSheets();
        if (sheet_size == 0) {
            throw new Exception("Excel内容为空！");
        }
    }
}
