package com.xhkjedu.slive.utils;

import com.xhkjedu.slive.model.liveplay.LCourse;
import com.xhkjedu.slive.model.xz.LXz;
import com.xhkjedu.slive.vo.gradeclass.CTeacherVo;
import com.xhkjedu.slive.vo.xz.XzKjVo;
import com.xhkjedu.utils.N_Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
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.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @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 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)) {
                    value = df.format(cell.getNumericCellValue());
                } 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内容为空！");
        }
    }

    /**
     * 课表导入
     *
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @Param [file, xz, xzService]
     * @Author ywx
     * @Date 2022/6/21 15:13
     **/
    public static Map<String, Object> readKb(MultipartFile file, LXz xz
            , Map<String, CTeacherVo> classTeacherMap, Set<String> userNameSet, List<XzKjVo> kjs) {
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, List<String>> errMsg = new LinkedHashMap<>();
        try {
            // 数据校验
            isExcelEmpty(file);
            InputStream in = file.getInputStream();
            String fileName = file.getOriginalFilename();
            Workbook work = getWorkbook(in, fileName);
            List<LCourse> kjTeas = new ArrayList<>();//行政直播课课节下班级和教师
            Integer timestamp = N_Utils.getSecondTimestamp();
            //要删除的行政直播id
            List<Integer> delCourseIds = kjs.stream().filter(c -> c.getCourseid() != null && c.getSectionstate() == 0
                            && new Integer(N_Utils.getDataToTimestamp(c.getSectiondate() + c.getBegintime()
                            , "yyyy-MM-ddHH:mm")).compareTo(timestamp) == 1)
                    .map(XzKjVo::getCourseid).collect(Collectors.toList());
            Sheet sheet;// 分表数据
            Row row;// 行数据
            int numberOfSheets = work.getNumberOfSheets();
            if (numberOfSheets > 7) numberOfSheets = 7;
            String enddate = xz.getEnddate();
            Integer daynum = xz.getDaynum();//第一列为班级
            Map<String, String> weeks = LiveUtil.listDateAfterDates2(xz.getBegindate(), enddate);
            Map<Integer, List<XzKjVo>> kjMap = kjs.stream().collect(Collectors.groupingBy(XzKjVo::getKjorder));
            for (int i = 0; i < numberOfSheets; i++) {
                sheet = work.getSheetAt(i);
                String sheetName = sheet.getSheetName();
                String sectiondate = weeks.get(sheetName);
                if (sectiondate == null) continue;//没有当天的课不处理
                int rows = sheet.getLastRowNum(); // 获取最后一个实际行的下标，比行数小1
                int firstRowNum = sheet.getFirstRowNum(); // 获取第一个实际行的下标，（firstRowNum=0）
                //遍历当前sheet中的所有行，排除第一行（标题）不纳入遍历
                for (int x = firstRowNum + 1; x <= rows; x++) {
                    // 获取行
                    row = sheet.getRow(x);
                    if (row == null) {//若此行为空，则跳出循环继续下一行
                        continue;
                    } else if (isEmptyCell(row.getCell(0))) {
                        continue;
                    }
                    int firstCellNum = row.getFirstCellNum();// 每一行的第一列，（firstCellNum=0）
                    int lastCellNum = row.getLastCellNum();// 每一行的最后一列，获取列数，比最后一列列标大1
                    if (lastCellNum > daynum) lastCellNum = daynum;//节数大于课程的节数不处理
                    List<String> mrows = new ArrayList<>();
                    String errMsgKey = sheetName + "第" + (x + 1) + "行";
                    //遍历所有的列
                    String classname = getCellValue(row.getCell(0));//第一列为班级
                    for (int y = firstCellNum + 1; y <= lastCellNum; y++) {
                        Cell cell = row.getCell(y);
                        String username = getCellValue(cell);
                        if (N_Utils.isEmpty(username)) {
                            if (y == lastCellNum && N_Utils.isListNotEmpty(mrows)) {
                                errMsg.put(errMsgKey, mrows);
                            }
                            continue;//教师为空执行下一条数据
                        }
                        CTeacherVo vo = classTeacherMap.get(classname + "_" + username);
                        Integer kjorder = y;//课节排序
                        XzKjVo kj = kjs.stream().filter(k -> k.getKjorder() == kjorder).findFirst().orElse(null);
                        String kjname = kj.getKjname();
                        if (!userNameSet.contains(username)) {
                            mrows.add(kjname + "【" + username + "】不存在");
                        } else if (vo == null) {
                            mrows.add(kjname + "【" + username + "】与【" + classname + "】不匹配");
                        } else if (N_Utils.isEmpty(vo.getSubjectid())) {
                            mrows.add(kjname + "【" + username + "】未设置科目");
                        } else {
                            String coursename = sheetName + kjname + vo.getSubjectname() + "(" + username + ")";
                            LCourse t = new LCourse();
                            Integer kjid = kjMap.get(y).get(0).getKjid();
                            t.setKjid(kjid);
                            t.setCoursename(coursename);
                            t.setClassid(vo.getClassid());
                            t.setSubjectid(vo.getSubjectid());
                            t.setTeacherid(vo.getTeacherid());
                            t.setBegintime(kj.getBegintime());
                            t.setEndtime(kj.getEndtime());
                            kj = kjs.stream().filter(k -> k.getKjorder() == kjorder
                                    && sectiondate.equals(k.getSectiondate())).findFirst().orElse(null);
                            Integer sectionstate = kj == null ? null : kj.getSectionstate();
                            String begintime = sectiondate + " " + t.getBegintime();
                            Integer beginTimestamp = N_Utils.getDataToTimestamp(begintime, "yyyy-MM-dd HH:mm");
                            if (beginTimestamp.compareTo(timestamp) == 1 && (sectionstate == null || sectionstate == 0)) {//已经开始或结束的课不处理
                                t.setBegindate(sectiondate);
                                t.setEnddate(sectiondate);
                                kjTeas.add(t);
                            }
                            List<String> meetDates = LiveUtil.getDaysForMeetDates(sectiondate, enddate);
                            for (int m = 1; m < meetDates.size(); m++) {
                                String date = meetDates.get(m);
                                begintime = date + " " + t.getBegintime();
                                beginTimestamp = N_Utils.getDataToTimestamp(begintime, "yyyy-MM-dd HH:mm");
                                if (beginTimestamp.compareTo(timestamp) != 1) continue;//如果课节开始时间不大于当前时间不处理

                                LCourse t2 = new LCourse();
                                BeanUtils.copyProperties(t, t2);
                                t2.setBegindate(date);
                                t2.setEnddate(date);
                                kjTeas.add(t2);
                            }
                        }
                        if (y == lastCellNum && N_Utils.isListNotEmpty(mrows)) {
                            errMsg.put(errMsgKey, mrows);
                        }
                    }
                }
            }

            resultMap.put("code", 0);
            resultMap.put("kjTeas", kjTeas);
            resultMap.put("delCourseIds", delCourseIds);
        } catch (Exception e) {
            resultMap.put("code", 1);
            resultMap.put("msg", e.getMessage());
            log.error("读取课表出错", e.getMessage());
        }
        resultMap.put("errMsg", errMsg);
        return resultMap;
    }
}
