package com.yida.data.school.transaction.service.impl;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.common.ResultMsgType;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.apply.EduStudentApply;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.system.Dept;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.ImportTemplateTypeEnum;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.common.core.utils.FileUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.school.transaction.listener.importStudentApplyListener;
import com.yida.data.school.transaction.mapper.EduStudentApplyMapper;
import com.yida.data.school.transaction.service.EduStudentApplyService;
import com.yida.data.school.vo.transcation.StudentApplyImportErrorVO;
import com.yida.data.school.vo.transcation.StudentApplyImportProgressVO;
import com.yida.data.school.vo.transcation.StudentApplyImportVO;
import com.yida.data.school.vo.transcation.StudentApplyStatusVO;
import com.yida.data.user.dto.ListStudentDTO;
import com.yida.data.user.dto.StudentErrorExportDTO;
import com.yida.data.user.dto.WelcomeInviteImportDTO;
import com.yida.data.user.feign.RemoteStudentService;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;
import javax.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import org.springframework.util.StopWatch;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@Service
@RequiredArgsConstructor
public class EduStudentApplyServiceImpl extends ServiceImpl<EduStudentApplyMapper, EduStudentApply> implements
    EduStudentApplyService {

    private final CommonService commonService;

    private final RedisService redisService;

    private final RemoteStudentService remoteStudentService;

    @Value("${febs.uploadUrl}")
    private String uploadUrl;

    @Override
    public StudentApplyStatusVO getStudentApplyStatus(Long studentId, String applyCode) {
        StudentApplyStatusVO applyStatus = new StudentApplyStatusVO();
        List<EduStudentApply> list = list(Wrappers.lambdaQuery(new EduStudentApply()).eq(EduStudentApply::getStudentId,
            studentId)
            .eq(EduStudentApply::getApplyCode, applyCode)
            .ge(EduStudentApply::getEndTime, LocalDateTime.now())
            .le(EduStudentApply::getStartTime, LocalDateTime.now()));
        if (CollUtil.isEmpty(list)) {
            List<EduStudentApply> applyList = baseMapper.getStudentApplyStatus(studentId, applyCode);
            if (CollUtil.isNotEmpty(applyList)) {
                applyStatus.setStatus(2);
                applyStatus.setDeadLine(applyList.get(0).getEndTime().toLocalDate().plusDays(1L));
            } else {
                applyStatus.setStatus(0);
            }
        } else {
            applyStatus.setStatus(1);
        }
        return applyStatus;
    }

    @Override
    public IPage<EduStudentApply> listStudentApply(String studentName, String studentNumber, Long schoolId, Long sectionId,
        Long campusId,
        Long gradeId, Long classId, Page<EduStudentApply> page) {
        IPage<EduStudentApply> eduStudentApplyIPage = this.baseMapper
            .listStudentApply(studentName, studentNumber, schoolId, sectionId, campusId, gradeId, classId, page);
        return eduStudentApplyIPage;
    }

    @Override
    public void downloadTemplate(HttpServletResponse response) throws Exception {

        String fileName = "学生开通应用导入模板.xls";
        // 获取导入文件模板
        ClassPathResource classPathResource = new ClassPathResource("template/" + fileName);
        InputStream inputStream = classPathResource.getInputStream();
        FileUtil.download(FileUtil.inputStreamToFile(inputStream), fileName, false, response);
    }

    @Override
    public void importStudentApplyInfo(MultipartFile file, String redisKey) throws IOException {
        log.info("开始导入学生开通应用数据");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        EasyExcel.read(file.getInputStream(), StudentApplyImportVO.class,
            new importStudentApplyListener(this, redisKey))
            .sheet(0).headRowNumber(1).doRead();
        stopWatch.stop();
        log.info("导入学生开通应用数据总共耗时: {}", stopWatch.getTotalTimeSeconds() + "秒");
    }

    @Override
    public void insertStudentApplyData(List<StudentApplyImportVO> studentApplyImportVOList, String redisKey) {
        StudentApplyImportProgressVO progressVO = new StudentApplyImportProgressVO();
        progressVO.setFinish(0);
        progressVO.setTotalNum(studentApplyImportVOList.size());
        progressVO.setCurrentNum(0);
        progressVO.setRedisKey(redisKey);
        redisService.hset(CachePrefixConstant.IMPORT_STUDENT_APPLY_PROGRESS, redisKey, progressVO);

        List<StudentApplyImportErrorVO> errorVOList = new ArrayList<>();
        List<EduStudentApply> saveData = new ArrayList<>();
        Integer index = 1;

        for (StudentApplyImportVO studentApplyImportVO : studentApplyImportVOList) {
            index++;
            String baseMag = "第" + index + "行，";
            StudentApplyImportErrorVO studentApplyImportErrorVO = checkImportDataIsNull(index, studentApplyImportVO);
            if (studentApplyImportErrorVO != null) {
                errorVOList.add(studentApplyImportErrorVO);
                continue;
            }
            Dept dept = commonService.getSchoolByName(studentApplyImportVO.getSchoolName());
            if (ObjectUtil.isNull(dept)) {
                StudentApplyImportErrorVO errorVO = new StudentApplyImportErrorVO();
                errorVO.setErrorMsg(baseMag + "学校名称不匹配");
                errorVOList.add(errorVO);
                continue;
            }
            // 根据学校ID、学号查询学生信息  检测学号与学生姓名是否匹配
            EduStudent student = new EduStudent();
            student.setSchoolId(dept.getDeptId());
            student.setStuNumber(studentApplyImportVO.getStudentNumber());
            List<EduStudent> currentStudentList = remoteStudentService.listBaseStudentNoJoin(student).getData();
            if (CollUtil.isEmpty(currentStudentList)) {
                StudentApplyImportErrorVO errorVO = new StudentApplyImportErrorVO();
                errorVO.setErrorMsg(baseMag + "学生学号有误");
                errorVOList.add(errorVO);
                continue;
            }
            if (!ObjectUtil.equal(studentApplyImportVO.getStudentName(), currentStudentList.get(0).getStuName())) {
                StudentApplyImportErrorVO errorVO = new StudentApplyImportErrorVO();
                errorVO.setErrorMsg(baseMag + "学生姓名与学号不匹配");
                errorVOList.add(errorVO);
                continue;
            }
            EduStudentApply eduStudentApply = new EduStudentApply();
            eduStudentApply.setStudentId(currentStudentList.get(0).getId());
            eduStudentApply.setApplyCode(studentApplyImportVO.getApplyCode());
            eduStudentApply
                .setStartTime(LocalDateTimeUtil
                    .parse(studentApplyImportVO.getStartTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
            eduStudentApply
                .setEndTime(LocalDateTimeUtil
                    .parse(studentApplyImportVO.getEndTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));
            saveData.add(eduStudentApply);

            progressVO.setCurrentNum(index - 1);
            redisService.hset(CachePrefixConstant.IMPORT_STUDENT_APPLY_PROGRESS, redisKey, progressVO);
        }
        if (CollUtil.isNotEmpty(saveData)) {
            super.saveBatch(saveData);
        }

        productErrorExcel(errorVOList, progressVO);
    }

    @Override
    public StudentApplyImportProgressVO getImportStudentApplyInfoProgress(String redisKey) {
        return (StudentApplyImportProgressVO) redisService
            .hget(CachePrefixConstant.IMPORT_STUDENT_APPLY_PROGRESS, redisKey);
    }


    public void productErrorExcel(List<StudentApplyImportErrorVO> errorVOList, StudentApplyImportProgressVO progressVO) {
        // 错误信息文件名称
        if (CollUtil.isNotEmpty(errorVOList)) {
            String fileName = FileUtil.getLocalUploadAddress() + UUID.randomUUID().toString() + ".xlsx";
            EasyExcel.write(fileName, StudentApplyImportErrorVO.class)
                .sheet("错误信息")
                .doWrite(errorVOList);
            // 上传到媒资
            String url = FileUtil.uploadFileToMediaServer(uploadUrl, new File(fileName));
            progressVO.setErrorPageUrl(url);
        }
        progressVO.setFinish(1);
        redisService.hset(CachePrefixConstant.IMPORT_STUDENT_APPLY_PROGRESS, progressVO.getRedisKey(), progressVO);
    }

    /**
     * 检测插入数据是否为空
     *
     * @return
     */
    public StudentApplyImportErrorVO checkImportDataIsNull(Integer index, StudentApplyImportVO studentApplyImportVO) {
        StudentApplyImportErrorVO studentApplyImportErrorVO = null;
        String baseMag = "第" + index + "行，";
        if (ObjectUtil.isNull(studentApplyImportVO.getSchoolName())) {
            studentApplyImportErrorVO = new StudentApplyImportErrorVO();
            studentApplyImportErrorVO.setErrorMsg(baseMag + "学校名称为空");
        }
        if (ObjectUtil.isNull(studentApplyImportVO.getStudentName())) {
            studentApplyImportErrorVO = new StudentApplyImportErrorVO();
            studentApplyImportErrorVO.setErrorMsg(baseMag + "学生姓名为空");
        }
        if (ObjectUtil.isNull(studentApplyImportVO.getStudentNumber())) {
            studentApplyImportErrorVO = new StudentApplyImportErrorVO();
            studentApplyImportErrorVO.setErrorMsg(baseMag + "学生学号为空");
        }
        if (ObjectUtil.isNull(studentApplyImportVO.getApplyCode())) {
            studentApplyImportErrorVO = new StudentApplyImportErrorVO();
            studentApplyImportErrorVO.setErrorMsg(baseMag + "开通应用为空");
        }
        if (ObjectUtil.isNull(studentApplyImportVO.getStartTime())) {
            studentApplyImportErrorVO = new StudentApplyImportErrorVO();
            studentApplyImportErrorVO.setErrorMsg(baseMag + "有效开始时间为空");
        }
        if (ObjectUtil.isNull(studentApplyImportVO.getStartTime())) {
            studentApplyImportErrorVO = new StudentApplyImportErrorVO();
            studentApplyImportErrorVO.setErrorMsg(baseMag + "有效结束时间为空");
        }
        return studentApplyImportErrorVO;
    }
}
