package com.qmth.distributed.print.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.boot.tools.excel.ExcelReader;
import com.qmth.boot.tools.excel.enums.ExcelType;
import com.qmth.distributed.print.business.bean.dto.TCUsualScoreDto;
import com.qmth.distributed.print.business.entity.TCUsualScore;
import com.qmth.distributed.print.business.mapper.TCUsualScoreMapper;
import com.qmth.distributed.print.business.service.PrintCommonService;
import com.qmth.distributed.print.business.service.TCUsualScoreService;
import com.qmth.distributed.print.business.service.TRBasicInfoService;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.FieldUniqueEnum;
import com.qmth.teachcloud.common.util.JacksonUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import com.qmth.teachcloud.mark.entity.MarkPaper;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 平常作业成绩表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2024-02-18
 */
@Service
public class TCUsualScoreServiceImpl extends ServiceImpl<TCUsualScoreMapper, TCUsualScore> implements TCUsualScoreService {
    private final static Logger log = LoggerFactory.getLogger(TCUsualScoreServiceImpl.class);

    @Resource
    PrintCommonService printCommonService;

    @Resource
    TCUsualScoreService tcUsualScoreService;

    @Resource
    TRBasicInfoService trBasicInfoService;

    /**
     * 导入平时成绩excel
     *
     * @param file
     * @param examId
     * @param courseCode
     * @param paperNumber
     * @param teachCourseId
     * @return
     * @throws IOException
     */
    @Override
    @Transactional
    public Map<String, String> usualScoreExcelImport(MultipartFile file, Long examId, String courseCode, String paperNumber, Long teachCourseId) throws IOException {
        log.debug("导入Excel开始...");
        long start = System.currentTimeMillis();
        Map<String, String> messageMap = new LinkedHashMap<>();
        try {
            MarkPaper markPaper = printCommonService.scoreImportExcelVaild(file, examId, courseCode, paperNumber);
            Double totalScore = 100d;

            StringJoiner errorData = new StringJoiner("");
            StringJoiner successData = new StringJoiner("");

            ExcelReader excelReader = ExcelReader.create(ExcelType.XLSX, file.getInputStream(), 1);
            List<String[]> arrayList = excelReader.getDataArrayList();
            if (!CollectionUtils.isEmpty(arrayList)) {
                log.info("arrayList:{}", JacksonUtil.parseJson(arrayList));
                SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
                List<TCUsualScore> tcUsualScoreList = new ArrayList<>(arrayList.size());
                String[] columnNames = excelReader.getColumnNames();
                for (int i = 0; i < columnNames.length; i++) {
                    if (i == 0 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "学号")) {
                        throw ExceptionResultEnum.ERROR.exception("excel表头第一行为学号");
                    } else if (i == 1 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "姓名")) {
                        throw ExceptionResultEnum.ERROR.exception("excel表头第二行为姓名");
                    }
                }

                for (int i = 0; i < arrayList.size(); i++) {
                    String[] strs = arrayList.get(i);
                    if (Objects.nonNull(strs) && strs.length > 0) {
                        if (strs.length != columnNames.length) {
                            throw ExceptionResultEnum.ERROR.exception("excel列和数据不匹配");
                        }
                        boolean error = false;
                        List<TCUsualScoreDto> tcUsualScoreDtoList = new ArrayList<>();
                        TCUsualScore tcUsualScore = new TCUsualScore(examId, courseCode, markPaper.getCourseName(), paperNumber, teachCourseId, sysUser.getId());
                        for (int j = 0; j < strs.length; j++) {
                            if (Objects.isNull(strs[j]) || Objects.equals(strs[j].trim(), "")) {
                                errorData.add("excel第").add((i + 1) + "").add("行[").add(columnNames[j] + "]为空;").add("\r\n");
                                error = true;
                            } else {
                                if (Objects.equals(columnNames[j].trim(), "学号")) {
                                    tcUsualScore.setStudentCode(strs[j]);
                                } else if (Objects.equals(columnNames[j].trim(), "姓名")) {
                                    tcUsualScore.setName(strs[j]);
                                } else {
                                    Double score = SystemConstant.isDouble(strs[j]);
                                    if (Objects.nonNull(score)) {
                                        if (score.doubleValue() > totalScore.doubleValue()) {
                                            errorData.add("excel第").add((i + 1) + "").add("行[").add(columnNames[j]).add("]总分大于试卷总分").add("\r\n");
                                            error = true;
                                        } else {
                                            tcUsualScoreDtoList.add(new TCUsualScoreDto(strs[j], columnNames[j]));
                                        }
                                    } else {
                                        errorData.add("excel第").add((i + 1) + "").add("行[").add(columnNames[j]).add("]请输入数字").add("\r\n");
                                        error = true;
                                    }
                                }
                            }
                        }
                        if (CollectionUtils.isNotEmpty(tcUsualScoreDtoList)) {
                            tcUsualScore.setScore(JacksonUtil.parseJson(tcUsualScoreDtoList));
                        }
                        if (!error) {
                            tcUsualScoreList.add(tcUsualScore);
                        }
                    }
                }
                if (!CollectionUtils.isEmpty(tcUsualScoreList)) {
                    successData.add("共导入").add(tcUsualScoreList.size() + "").add("条数据");
                    List<TCUsualScore> tcUsualScoreDbSourceList = tcUsualScoreService.queryUsualScore(examId, courseCode, paperNumber, teachCourseId);
                    if (CollectionUtils.isEmpty(tcUsualScoreDbSourceList) || !CollectionUtils.isEqualCollection(tcUsualScoreDbSourceList, tcUsualScoreList)) {
                        tcUsualScoreService.removeByIds(tcUsualScoreDbSourceList.stream().map(s -> s.getId()).collect(Collectors.toList()));
                        tcUsualScoreService.saveBatch(tcUsualScoreList);
                        trBasicInfoService.clearReportData(examId, courseCode, paperNumber, teachCourseId, false);
                    }
                }
            }
            messageMap.put(SystemConstant.SUCCESS, successData.length() > 0 ? successData.toString() : "无");
            messageMap.put(SystemConstant.EXCEL_ERROR, errorData.length() > 0 ? errorData.toString() : "无");
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
                throw ExceptionResultEnum.SQL_ERROR.exception("[" + FieldUniqueEnum.convertToTitle(columnStr) + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        log.debug("导入Excel结束...");
        long end = System.currentTimeMillis();
        log.info("============耗时{}秒============:", (end - start) / 1000);
        return messageMap;
    }

    /**
     * 平时成绩列表（分页）
     *
     * @param iPage
     * @param examId
     * @param courseCode
     * @param paperNumber
     * @param teachCourseId
     * @return
     */
    @Override
    public IPage<TCUsualScore> usualScoreList(IPage<Map> iPage, Long examId, String courseCode, String paperNumber, Long teachCourseId) {
        return this.baseMapper.usualScoreList(iPage, examId, courseCode, paperNumber, teachCourseId);
    }

    /**
     * 根据考试id/课程编码/试卷编码查询数据库数据
     *
     * @param examId
     * @param courseCode
     * @param paperNumber
     * @param teachCourseId
     * @return
     */
    @Override
    public List<TCUsualScore> queryUsualScore(Long examId, String courseCode, String paperNumber, Long teachCourseId) {
        QueryWrapper<TCUsualScore> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TCUsualScore::getExamId, examId).eq(TCUsualScore::getCourseCode, courseCode);
        if (Objects.nonNull(paperNumber)) {
            queryWrapper.lambda().and(w -> w.eq(TCUsualScore::getPaperNumber, paperNumber).or().isNull(TCUsualScore::getPaperNumber));
        }
        queryWrapper.lambda().eq(TCUsualScore::getTeachCourseId, teachCourseId);
        return tcUsualScoreService.list(queryWrapper);
    }
}
