package com.xhkjedu.suser.utils;

import com.xhkjedu.suser.model.system.TUser;
import com.xhkjedu.utils.MD5;
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;

/**
 * @author ywx
 * @classname PoiUtils
 * @description
 * @date 2020/6/3 16:33
 **/
@Component
@Slf4j
public class PoiUtils {
    //2003- 版本的excel
    private final static String excel2003L = ".xls";
    //2007+ 版本的excel
    private final static String excel2007U = ".xlsx";

    /**
     * 导入班级学生
     *
     * @return java.lang.String
     * @Param [file]
     * @Author ywx
     * @Date 2020/6/3 16:43
     **/
    public static Map<String, Object> readExcelStudent(MultipartFile file, Map<Integer, List<Map<String, Integer[]>>> gcg) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            // 数据校验
            isExcelEmpty(file);
            InputStream in = file.getInputStream();
            String fileName = file.getOriginalFilename();
            Workbook work = getWorkbook(in, fileName);
            Sheet sheet;// 分表数据
            Row row;// 行数据
            sheet = work.getSheetAt(0);//只取第一个sheet
            if (sheet == null) {
                throw new Exception("Excel第一个分表内容为空！");
            }

            int rows = sheet.getLastRowNum(); // 获取最后一个实际行的下标，比行数小1
            int firstRowNum = sheet.getFirstRowNum(); // 获取第一个实际行的下标，（firstRowNum=0）
            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));//班级
            sb.append(row.getCell(5));//准考证号
            String importTitleName = sb.toString().replaceAll(" |（必填）", "");
            if(!titleName.equals(importTitleName)) throw new Exception("标题格式不正确");

            // 导入用户信息
            List<TUser> users = new ArrayList<>();
            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;
                }
                TUser user = new TUser();// 每一行一个学生信息
                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) {   // 姓名
                        setUserName(cell, x, user);
                    } else if (y == 1) {// 登录名
                        if (isEmptyCell(cell)) {
                            throw new Exception("第" + (x + 1) + "行登录学号不能为空");
                        } else {
                            String loginname = getCellValue(cell);
                            user.setLoginname(loginname);//登录名默认为学号
                            user.setStudentno(loginname);
                            MD5 md5 = new MD5();
                            user.setLoginpwd(md5.getMD5ofStr(md5.getMD5ofStr(md5.getMD5ofStr("123456"))));
                        }
                    } else if (y == 2) {//性别
                        if (isEmptyCell(cell)) {
                            user.setUsersex(0);
                        } else {
                            String usersex = getCellValue(cell);
                            if (usersex.equals("女")) {
                                user.setUsersex(2);
                            } else if (usersex.equals("男")) {
                                user.setUsersex(1);
                            } else {
                                user.setUsersex(0);
                            }
                        }
                    } else if (y == 3) {//年级
                        if (isEmptyCell(cell)) {
                            throw new Exception("第" + (x + 1) + "行年级不能为空");
                        } else {
                            String gradename = getCellValue(cell);
                            Map<String, Integer> grades = N_Utils.listGrade();
                            if (!grades.containsKey(gradename)) {
                                throw new Exception("第" + (x + 1) + "行年级不存在");
                            } else {
                                Integer gradeid = grades.get(gradename);
                                if (gcg.containsKey(gradeid)) {
                                    user.setGrageid(gradeid);
                                } else {
                                    throw new Exception("第" + (x + 1) + "行年级不存在");
                                }
                            }
                        }
                    } else if (y == 4) {//班级
                        if (isEmptyCell(cell)) {
                            throw new Exception("第" + (x + 1) + "行班级不能为空");
                        } else {
                            String classname = getCellValue(cell);
                            List<Map<String, Integer[]>> allclasslist = gcg.get(user.getGrageid());//获取学校年级下班级集合
                            //符合条件的班级集合
                            Map<String, Integer[]> ccobj = null;
                            for (Map<String, Integer[]> m : allclasslist) {
                                if (m.get(classname) != null) {
                                    ccobj = m;
                                    break;
                                }
                            }

                            if (ccobj != null) {
                                Integer[] class_group = ccobj.get(classname);
                                user.setClassid(class_group[0]);
                                user.setGroupid(class_group[1]);
                                user.setYear(class_group[2]);
                            } else {
                                throw new Exception("第" + (x + 1) + "行班级不存在");
                            }
                        }
                    } else if (y == 5) {//准考证号
                        String examno = getCellValue(cell);
                        if (N_Utils.isNotEmpty(examno)) user.setExamno(examno);
                    }
                }

                String loginname = user.getLoginname();
                if (N_Utils.isNotEmpty(nameMap.get(loginname))) {

                } else {
                    nameMap.put(loginname, loginname);
                    users.add(user);
                }
            }

            resultMap.put("code", 0);
            resultMap.put("users", users);
        } catch (Exception e) {
            resultMap.put("code", 1);
            String msg=e.getMessage();
            resultMap.put("msg", msg);
            if (msg.contains("Invalid ")) {
                msg = "格式不正确";
            }
            throw new Exception(msg);
        }
        return resultMap;
    }

    /**
     * 导入教师
     * @Param [file]
     * @Author ywx
     * @Date 2022/3/17 9:44
     * @return java.util.Map<java.lang.String,java.lang.Object>
     **/
    public static Map<String, Object> readExcelTeacher(MultipartFile file, Map<Integer, Map<String, Integer>> gclasses) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            // 数据校验
            isExcelEmpty(file);
            InputStream in = file.getInputStream();
            String fileName = file.getOriginalFilename();
            Workbook work = getWorkbook(in, fileName);
            Sheet sheet;// 分表数据
            Row row;// 行数据
            sheet = work.getSheetAt(0);//只取第一个sheet
            if (sheet == null) {
                throw new Exception("Excel第一个分表内容为空！");
            }

            int rows = sheet.getLastRowNum(); // 获取最后一个实际行的下标，比行数小1
            int firstRowNum = sheet.getFirstRowNum(); // 获取第一个实际行的下标，（firstRowNum=0）
            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));//出生日期
            sb.append(row.getCell(5));//身份证号
            sb.append(row.getCell(6));//年级
            sb.append(row.getCell(7));//班级
            String importTitleName = sb.toString().replaceAll(" |（必填）", "");
            if(!titleName.equals(importTitleName)) throw new Exception("标题格式不正确");

            // 导入用户信息
            List<TUser> users = new ArrayList<>();
            Map<String, String> nameMap = new HashMap<>();
            Map<String, Integer> grades = N_Utils.listGrade();

            //遍历当前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;
                }
                TUser user = new TUser();// 每一行一个学生信息
                user.setUsertype(1);
                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) {   // 姓名
                        setUserName(cell, x, user);
                    } else if (y == 1) {// 登录名
                        if (isEmptyCell(cell)) {
                            throw new Exception("第" + (x + 1) + "行登录账号不能为空");
                        } else {
                            String loginname = getCellValue(cell);
                            user.setLoginname(loginname);//登录名默认为学号
                            user.setLoginpwd("123456");
                        }
                    } else if (y == 2) {//性别
                        if (isEmptyCell(cell)) {
                            user.setUsersex(0);
                        } else {
                            String usersex = getCellValue(cell);
                            if (usersex.equals("女")) {
                                user.setUsersex(2);
                            } else if (usersex.equals("男")) {
                                user.setUsersex(1);
                            } else {
                                user.setUsersex(0);
                            }
                        }
                    } else if (y == 3) {//手机号
                        setUserPhone(cell, x, user);
                    } else if (y == 4) {//出生日期
                        if (!isEmptyCell(cell)) {
                            String birthDay = getCellValue(cell);
                            birthDay = birthDay.replaceAll("-", "").replaceAll("/", "");
                            if (birthDay.length() != 8) {
                                throw new Exception("第" + (x + 1) + "行出生日期格式不对");
                            } else {
                                user.setUserbirthday(N_Utils.getDataToTimestamp(birthDay, "yyyyMMdd"));
                            }
                        }
                    } else if (y == 5) {//身份证号
                        if (isEmptyCell(cell)) {
                            user.setCardid("");
                        } else {
                            user.setCardid(getCellValue(cell));
                        }
                    } else if (y == 6) {//年级
                        if (!isEmptyCell(cell)) {
                            Integer grageid = grades.get(getCellValue(cell));
                            if (N_Utils.isEmptyInteger(grageid) || !gclasses.containsKey(grageid)) {
                                throw new Exception("第" + (x + 1) + "行年级不存在");
                            }
                            user.setGrageid(grageid);
                        }
                    } else if (y == 7) {//班级
                        if (!isEmptyCell(cell)) {
                            //去首尾空格和换行符
                            String classname = getCellValue(cell).replaceAll("^\\s*|\\s*$|\\t|\\n|\\r", "");
                            classname = classname.replaceAll("，|、", ",");
                            List<Integer> classids = new ArrayList<>();//班级ids
                            String[] classenames = classname.split(",");
                            Integer grageid = user.getGrageid();
                            if (N_Utils.isEmptyInteger(grageid)) {
                                throw new Exception("第" + (x + 1) + "行年级不存在");
                            }
                            Map<String, Integer> maps = gclasses.get(user.getGrageid());
                            for (String classename : classenames) {
                                Integer classid = maps.get(classename);
                                if (N_Utils.isEmptyInteger(classid)) {
                                    throw new Exception("第" + (x + 1) + "行班级【" + classename + "】不存在");
                                }
                                classids.add(classid);
                            }
                            user.setClassids(classids);
                        }
                    }
                }

                String loginname = user.getLoginname();
                if (N_Utils.isEmpty(nameMap.get(loginname))) {
                    nameMap.put(loginname, loginname);
                    users.add(user);
                }
            }

            resultMap.put("code", 0);
            resultMap.put("users", users);
        } catch (Exception e) {
            resultMap.put("code", 1);
            String msg=e.getMessage();
            resultMap.put("msg", msg);
            if (msg.contains("Invalid ")) {
                msg = "格式不正确";
            }
            throw new Exception(msg);
        }

        return resultMap;
    }

    private static void setUserName(Cell cell, int x, TUser user) throws Exception {
        if (isEmptyCell(cell)) {
            throw new Exception("第" + (x + 1) + "行姓名不能为空");
        } else {
            user.setUsername(getCellValue(cell));
        }
    }

    private static void setUserPhone(Cell cell, int x, TUser user) throws Exception {
        if (isEmptyCell(cell)) {
            user.setUserphone("");
        } else {
            String phone = getCellValue(cell);
            if (!N_Utils.isPhone(phone)) {
                throw new Exception("第" + (x + 1) + "行手机号码格式不正确");
            }
            user.setUserphone(phone);
        }
    }

    /**
     * 根据文件后缀，自适应上传文件的版本
     *
     * @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(PoiUtils.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 {
                    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内容为空！");
        }
    }
}
