package com.template.controller;


import com.template.api.SmartScoreControllerAPI;
import com.template.common.utils.ExcelUtils;
import com.template.common.utils.paramUtils;
import com.template.model.enumModel.*;
import com.template.model.pojo.SmartScore;
import com.template.model.pojo.SmartUser;
import com.template.model.request.deleteSmartScoreRequest;
import com.template.model.request.insertScoreRequest;
import com.template.model.request.updateScoreRequest;
import com.template.model.result.CommonResult;
import com.template.model.result.PageUtils;
import com.template.model.vo.*;
import com.template.services.SmartScoreService;
import com.template.services.SmartUserService;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.DataFormatter;
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.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 楼栋表 前端控制器
 * </p>
 *
 * @author ceshi
 * @since 2024-01-02
 */
@RestController
public class SmartScoreController implements SmartScoreControllerAPI {

    @Autowired
    private SmartScoreService smartScoreService;

    @Autowired
    private SmartUserService smartUserService;

    @Override
    public CommonResult querySmartSemesters() {
        //判断当前时间的月份
        // 2月-6月底是春季学期
        // 9月-次年1月底是秋季学期
        List<SmartScore> scores = smartScoreService.list(null);
        List<String> semesters = scores.stream().map(SmartScore::getSemester).distinct().collect(Collectors.toList());

        return CommonResult.ok(semesters);
    }

    @Override
    public CommonResult queryUserGrade(int userId) {
        //判断学生是否有效
        SmartUser user = smartUserService.getSmartById(userId);
        if (user == null) {
            return CommonResult.fail("学生信息无效，无法获取年级、班级和学号");
        }

        if (eIdentityStatu.Student.getValue() != user.getIdentityId().intValue()) {
            return CommonResult.fail("选择的用户身份非学生，无法获取年级、班级和学号");
        }

        GradeVo result = new GradeVo();
        result.setGrade(user.getGrade());
        result.setSchoolClass(user.getSchoolClass());
        result.setCardNo(user.getCardNo());

        return CommonResult.ok(result);
    }

    @Override
    public CommonResult querySubjects() {
        List<SemesterVo> semesters = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            SemesterVo semester = new SemesterVo();
            semester.setId(i);
            semester.setName(eSubjectStatu.stringOf(i));
            semesters.add(semester);
        }

        return CommonResult.ok(semesters);
    }

    @Override
    public CommonResult queryExamTypes() {
        List<SemesterVo> semesters = new ArrayList<>();
        for (int i = 1; i <= 2; i++) {
            SemesterVo semester = new SemesterVo();
            semester.setId(i);
            semester.setName(eExamType.stringOf(i));
            semesters.add(semester);
        }

        return CommonResult.ok(semesters);
    }

    @Override
    public CommonResult querySmartSecordPage(int currentPage, int pageCount, String name) {
        PageUtils<GradeVo> result = smartUserService.querySmartSecordPage(currentPage, pageCount, name);
        return CommonResult.ok(result);
    }

    /**
     * 明天补查询条件
     *
     * @param currentPage
     * @param pageCount
     * @return
     */
    /**
     * 按学期、年级、班级、学科、考试类型 和 成绩进行查询
     * 获取成绩分页数据
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param name        学号或名称
     * @param semester    学期 需要转换为int
     * @param grade       年级
     * @param schoolClass 班级
     * @param subject     科目 需要转换为int
     * @param examType    考试类型 需要转换为int
     * @param MinScore    最低成绩
     * @param MaxScore    最高成绩
     * @return
     */
    @Override
    public CommonResult querySmartScorePage(int currentPage, int pageCount, String name, String semester, String grade, String schoolClass, String subject, String examType, Double MinScore, Double MaxScore) {

        Integer subjectInt = subject == null ? null : eSubjectStatu.integerOf(subject);
        Integer examTypeInt = examType == null ? null : eExamType.integerOf(examType);

        PageUtils<ScorePageVo> pageData = smartScoreService.querySmartScorePage(currentPage, pageCount, name, semester, grade, schoolClass, subjectInt, examTypeInt, MinScore, MaxScore);

        PageUtils<ScoreVo> result = null;

        if (pageData != null) {
            List<ScoreVo> datas = new ArrayList<>();
            for (ScorePageVo spv : pageData.getList()) {
                ScoreVo data = new ScoreVo();
                data.setId(spv.getId());
                data.setSemester(spv.getSemester());
                data.setGrade(spv.getGrade());
                data.setGradeId(spv.getGradeId());
                data.setSchoolClass(spv.getSchoolClass());
                data.setSchoolClassId(spv.getSchoolClassId());
                data.setSubject(spv.getSubjectId());
                data.setSubjectStr(eSubjectStatu.stringOf(spv.getSubjectId()));
                data.setExamType(spv.getExamType());
                data.setExamTypeStr(eExamType.stringOf(spv.getExamType()));
                data.setName(spv.getName());
                data.setUserId(spv.getUserId());
                data.setCardNo(spv.getCardNo());
                data.setScore(spv.getScore());
                datas.add(data);
            }

            result = new PageUtils<ScoreVo>(datas, pageData.getTotalCount(), pageData.getPageSize(), pageData.getCurrPage());
        }

        return CommonResult.ok(result);
    }

    @Override
    public CommonResult insertSmartScore(insertScoreRequest isr, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        //判断学生是否有效
        SmartUser user = smartUserService.getSmartById(isr.getUserId());
        if (user == null) {
            return CommonResult.fail("学生信息无效，无法添加学生成绩");
        }

        if (eIdentityStatu.Student.getValue() != user.getIdentityId().intValue()) {
            return CommonResult.fail("选择的用户身份非学生，无法添加成绩");
        }

        SmartScore ss = new SmartScore();
        ss.setSemester(isr.getSemester());
        ss.setGrade(isr.getGrade());
        ss.setGradeId(isr.getGradeId());
        ss.setSchoolClass(isr.getSchoolClass());
        ss.setSchoolClassId(isr.getSchoolClassId());
        ss.setCardNo(isr.getCardNo());
        ss.setUserId(isr.getUserId());
        ss.setName(user.getName());
        ss.setSubjectId(isr.getSubjectId());
        ss.setExamType(isr.getExamType());
        ss.setScore(isr.getScore());

        int result = smartScoreService.insertSmartScore(ss);

        return result > 0 ? CommonResult.ok("添加成功") : CommonResult.fail("添加失败");
    }

    @Override
    public CommonResult updateSmartScoreById(updateScoreRequest usr, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        SmartScore score = smartScoreService.getSmartById(usr.getId());
        if (score == null) {
            return CommonResult.fail("成绩数据无效，无法编辑");
        }

        //判断学生是否有效
        SmartUser user = smartUserService.getSmartById(usr.getUserId());
        if (user == null) {
            return CommonResult.fail("学生信息无效，无法编辑学生成绩");
        }

        if (eIdentityStatu.Student.getValue() != user.getIdentityId().intValue()) {
            return CommonResult.fail("选择的用户身份非学生，无法编辑成绩");
        }

        score.setSemester(usr.getSemester());
        score.setGradeId(usr.getGradeId());
        score.setGrade(usr.getGrade());
        score.setSchoolClassId(usr.getSchoolClassId());
        score.setSchoolClass(usr.getSchoolClass());
        score.setCardNo(usr.getCardNo());
        score.setUserId(usr.getUserId());
        score.setName(user.getName());
        score.setSubjectId(usr.getSubjectId());
        score.setExamType(usr.getExamType());
        score.setScore(usr.getScore());


        int result = smartScoreService.updateSmartScore(score);

        return result > 0 ? CommonResult.ok("编辑成功") : CommonResult.fail("编辑失败");
    }

    @Override
    public CommonResult querySmartScore() {
        return null;
    }

    @Override
    public CommonResult queryPageSmartScores(int currentPage, int pageCount, String name) {
        return null;
    }

    @Override
    public CommonResult deleteSmartScoreById(int id) {
        return null;
    }

    @Override
    public CommonResult deleteSmartScoresByIds(deleteSmartScoreRequest dssr, BindingResult bindingResult) {
        int result = smartScoreService.deleteSmartScoreByIds(dssr.getIds());

        return result > 0 ? CommonResult.ok("删除成功") : CommonResult.fail("删除失败");
    }

    @Override
    public void smartUserExport(HttpServletResponse response, String name, String semester, String grade, String schoolClass, String subject, String examType, Double MinScore, Double MaxScore) {

        Integer subjectInt = subject == null ? null : eSubjectStatu.integerOf(subject);
        Integer examTypeInt = examType == null ? null : eExamType.integerOf(examType);

        //获取成绩
        List<ScorePageVo> scores = smartScoreService.querySmartScores(name, semester, grade, schoolClass, subjectInt, examTypeInt, MinScore, MaxScore);

        //导出
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("成绩管理");
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("序号");
        headerRow.createCell(1).setCellValue("学期");
        headerRow.createCell(2).setCellValue("年级");
        headerRow.createCell(3).setCellValue("班级");
        headerRow.createCell(4).setCellValue("学科");
        headerRow.createCell(5).setCellValue("考试类型");
        headerRow.createCell(6).setCellValue("姓名");
        headerRow.createCell(7).setCellValue("学号");
        headerRow.createCell(8).setCellValue("成绩");

        for (int i = 0; i < scores.size(); i++) {
            ScorePageVo score = scores.get(i);

            Row dataRow = sheet.createRow(i + 1);
            dataRow.createCell(0).setCellValue(i + 1);
            dataRow.createCell(1).setCellValue(score.getSemester());
            dataRow.createCell(2).setCellValue(score.getGrade());
            dataRow.createCell(3).setCellValue(score.getSchoolClass());
            dataRow.createCell(4).setCellValue(eSubjectStatu.stringOf(score.getSubjectId()));
            dataRow.createCell(5).setCellValue(eExamType.stringOf(score.getExamType()));
            dataRow.createCell(6).setCellValue(score.getName());
            dataRow.createCell(7).setCellValue(score.getCardNo());
            dataRow.createCell(8).setCellValue(score.getScore());
        }

        // 将工作簿写入文件
        ExcelUtils.excelDownload(workbook, "成绩信息.xlsx", response);
    }

    @Override
    public CommonResult importSmartScoreExcel(MultipartFile file) throws IOException {
        if(file.isEmpty() || file.getSize() == 0){
            return CommonResult.fail("导入文件不能为空");
        }

        String ContentType = file.getContentType();
        InputStream inputStream = file.getInputStream();
        List<SmartScore> result = new ArrayList<>();

        //xls格式文件
        if(ContentType.equals(eFileType.Xls.getValue())){
            CommonResult<List<SmartScore>> resultData = readXls(inputStream);
            if(!resultData.isSuccess()){
                return resultData;
            }
            result = resultData.getData();
        }else if(ContentType.equals(eFileType.Xlsx.getValue())){
            CommonResult<List<SmartScore>> resultData = readXlsx(inputStream);
            if(!resultData.isSuccess()){
                return resultData;
            }
            result = resultData.getData();
        }else{
            return CommonResult.fail("耗材数据导入只支持Xls、Xlsx");
        }

        boolean resultBool = smartScoreService.saveBatch(result);

        return resultBool ? CommonResult.ok("导入成功") : CommonResult.fail("导入失败");
    }

    @Override
    public CommonResult downloadScoreExcel() {
        return CommonResult.ok("200","操作成功","https://wanzai-1306339220.cos.ap-shanghai.myqcloud.com/excelModel/成绩信息表.xlsx");
    }

    /**
     * 导入Xls文件方法
     * @param inputStream 文件流
     * @return
     * @throws IOException
     */
    private CommonResult<List<SmartScore>> readXls(InputStream inputStream) throws IOException {
        HSSFWorkbook sheets = new HSSFWorkbook(inputStream);
        List<SmartScore> result = new ArrayList<>();
        List<String> scoreNames = new ArrayList<>();
        //读取第一张sheet
        HSSFSheet sheetAt = sheets.getSheetAt(0);

        //获取成绩数据
        List<SmartScore> scores = smartScoreService.list(null);
        //获取学生数据
        List<SmartUser> users = smartUserService.queryStudentDatas();

        DataFormatter dataFormatter = new DataFormatter();

        try{
            //sheetAt.getLastRowNum()：从0开始统计数量 所以得+1
            for (int rowNum = 0;rowNum < sheetAt.getLastRowNum();rowNum++){

                HSSFRow row = sheetAt.getRow(rowNum);

                //判断每一列单元格是否符合规则
                if(rowNum == 0){
                    String semester = dataFormatter.formatCellValue(row.getCell(0));//学期
                    if (!semester.equals("学期")) {
                        return CommonResult.fail("导入数据第一列为学期");
                    }
                    String grade = dataFormatter.formatCellValue(row.getCell(1));//年级
                    if (!grade.equals("年级")) {
                        return CommonResult.fail("导入数据第二列为年级");
                    }
                    String schoolClass = dataFormatter.formatCellValue(row.getCell(2));//班级
                    if (!schoolClass.equals("班级")) {
                        return CommonResult.fail("导入数据第三列为班级");
                    }
                    String subject = dataFormatter.formatCellValue(row.getCell(3));//学科
                    if (!subject.equals("学科")) {
                        return CommonResult.fail("导入数据第四列为学科");
                    }
                    String examType = dataFormatter.formatCellValue(row.getCell(4));//考试类型
                    if (!examType.equals("考试类型")) {
                        return CommonResult.fail("导入数据第四列为考试类型");
                    }
                    String name = dataFormatter.formatCellValue(row.getCell(5));//姓名
                    if (!name.equals("姓名")) {
                        return CommonResult.fail("导入数据第四列为姓名");
                    }
                    String cardNo = dataFormatter.formatCellValue(row.getCell(6));//学号
                    if (!cardNo.equals("学号")) {
                        return CommonResult.fail("导入数据第四列为学号");
                    }
                    String score = dataFormatter.formatCellValue(row.getCell(7));//成绩
                    if (!score.equals("成绩")) {
                        return CommonResult.fail("导入数据第四列为成绩");
                    }
                }else{
                    SmartScore data = new SmartScore();
                    String semester = dataFormatter.formatCellValue(row.getCell(0));//学期
                    String grade = dataFormatter.formatCellValue(row.getCell(1));//年级
                    String schoolClass = dataFormatter.formatCellValue(row.getCell(2));//班级
                    String subject = dataFormatter.formatCellValue(row.getCell(3));//学科
                    String examType = dataFormatter.formatCellValue(row.getCell(4));//考试类型
                    String name = dataFormatter.formatCellValue(row.getCell(5));//姓名
                    String cardNo = dataFormatter.formatCellValue(row.getCell(6));//学号
                    String score = dataFormatter.formatCellValue(row.getCell(7));//成绩

                    //数据重复性判断 学期 + 学号 + 科目
                    String existData = semester + cardNo + subject;
                    scoreNames.add(existData);
                    if(scoreNames.stream().distinct().count() != scoreNames.size()){
                        return CommonResult.fail("导入的Excel中的"+existData+"存在重复数据");
                    }

                    //重复数据提示
                    long exist = scores.stream().filter(e -> e.getSemester().equals(semester) && e.getCardNo().equals(cardNo) && e.getSubjectId().equals(eSubjectStatu.integerOf(subject))).count();
                    if (exist > 0) {
                        return CommonResult.fail(existData + "成绩数据在系统中已存在，请勿重复导入");
                    }

                    data.setSemester(semester);
                    data.setGrade(grade);
                    data.setSchoolClass(schoolClass);
                    data.setCardNo(cardNo);
                    data.setName(name);
                    Optional<SmartUser> user = users.stream().filter(e -> e.getCardNo().equals(cardNo)).findFirst();
                    if(user != null && user.isPresent()){
                        data.setUserId(user.get().getId());
                    }else{
                        return CommonResult.fail("当前系统中不存在"+name+"的学生信息，无法导入成绩");
                    }
                    data.setSubjectId(eSubjectStatu.integerOf(subject));
                    data.setExamType(eExamType.integerOf(examType));
                    data.setScore(Double.valueOf(score));

                    result.add(data);
                }
            }
        }catch (Exception e){
            return CommonResult.fail("请按模板格式导入数据");
        }

        return CommonResult.ok(result);
    }

    /**
     * 导入Xlsx文件方法
     * @param inputStream 文件流
     * @return
     * @throws IOException
     */
    private CommonResult<List<SmartScore>> readXlsx(InputStream inputStream) throws IOException {
        XSSFWorkbook sheets = new XSSFWorkbook(inputStream);
        List<SmartScore> result = new ArrayList<>();
        List<String> scoreNames = new ArrayList<>();
        //读取第一张sheet
        XSSFSheet sheetAt = sheets.getSheetAt(0);

        //获取成绩数据
        List<SmartScore> scores = smartScoreService.list(null);
        //获取学生数据
        List<SmartUser> users = smartUserService.queryStudentDatas();

        DataFormatter dataFormatter = new DataFormatter();

        try{
            //sheetAt.getLastRowNum()：从0开始统计数量 所以得+1
            for (int rowNum = 0;rowNum < sheetAt.getLastRowNum();rowNum++){

                XSSFRow row = sheetAt.getRow(rowNum);

                //判断每一列单元格是否符合规则
                if(rowNum == 0){
                    String semester = dataFormatter.formatCellValue(row.getCell(0));//学期
                    if (!semester.equals("学期")) {
                        return CommonResult.fail("导入数据第一列为学期");
                    }
                    String grade = dataFormatter.formatCellValue(row.getCell(1));//年级
                    if (!grade.equals("年级")) {
                        return CommonResult.fail("导入数据第二列为年级");
                    }
                    String schoolClass = dataFormatter.formatCellValue(row.getCell(2));//班级
                    if (!schoolClass.equals("班级")) {
                        return CommonResult.fail("导入数据第三列为班级");
                    }
                    String subject = dataFormatter.formatCellValue(row.getCell(3));//学科
                    if (!subject.equals("学科")) {
                        return CommonResult.fail("导入数据第四列为学科");
                    }
                    String examType = dataFormatter.formatCellValue(row.getCell(4));//考试类型
                    if (!examType.equals("考试类型")) {
                        return CommonResult.fail("导入数据第四列为考试类型");
                    }
                    String name = dataFormatter.formatCellValue(row.getCell(5));//姓名
                    if (!name.equals("姓名")) {
                        return CommonResult.fail("导入数据第四列为姓名");
                    }
                    String cardNo = dataFormatter.formatCellValue(row.getCell(6));//学号
                    if (!cardNo.equals("学号")) {
                        return CommonResult.fail("导入数据第四列为学号");
                    }
                    String score = dataFormatter.formatCellValue(row.getCell(7));//成绩
                    if (!score.equals("成绩")) {
                        return CommonResult.fail("导入数据第四列为成绩");
                    }
                }else{
                    SmartScore data = new SmartScore();
                    String semester = dataFormatter.formatCellValue(row.getCell(0));//学期
                    String grade = dataFormatter.formatCellValue(row.getCell(1));//年级
                    String schoolClass = dataFormatter.formatCellValue(row.getCell(2));//班级
                    String subject = dataFormatter.formatCellValue(row.getCell(3));//学科
                    String examType = dataFormatter.formatCellValue(row.getCell(4));//考试类型
                    String name = dataFormatter.formatCellValue(row.getCell(5));//姓名
                    String cardNo = dataFormatter.formatCellValue(row.getCell(6));//学号
                    String score = dataFormatter.formatCellValue(row.getCell(7));//成绩

                    //数据重复性判断 学期 + 学号 + 科目
                    String existData = semester + cardNo + subject;
                    scoreNames.add(existData);
                    if(scoreNames.stream().distinct().count() != scoreNames.size()){
                        return CommonResult.fail("导入的Excel中的"+existData+"存在重复数据");
                    }

                    //重复数据提示
                    long exist = scores.stream().filter(e -> e.getSemester().equals(semester) && e.getCardNo().equals(cardNo) && e.getSubjectId().equals(eSubjectStatu.integerOf(subject))).count();
                    if (exist > 0) {
                        return CommonResult.fail(existData + "成绩数据在系统中已存在，请勿重复导入");
                    }

                    data.setSemester(semester);
                    data.setGrade(grade);
                    data.setSchoolClass(schoolClass);
                    data.setCardNo(cardNo);
                    data.setName(name);
                    Optional<SmartUser> user = users.stream().filter(e -> e.getCardNo().equals(cardNo)).findFirst();
                    if(user != null && user.isPresent()){
                        data.setUserId(user.get().getId());
                    }else{
                        return CommonResult.fail("当前系统中不存在"+name+"的学生信息，无法导入成绩");
                    }
                    data.setSubjectId(eSubjectStatu.integerOf(subject));
                    data.setExamType(eExamType.integerOf(examType));
                    data.setScore(Double.valueOf(score));

                    result.add(data);
                }
            }
        }catch (Exception e){
            return CommonResult.fail("请按模板格式导入数据");
        }

        return CommonResult.ok(result);
    }
}

