package cn.exploring.engine.server.db.service;

import cn.exploring.engine.server.db.dao.SpecialSqlMapper;
import cn.exploring.engine.server.db.dao.StudentPointInfoMapper;
import cn.exploring.engine.server.db.domain.StudentInfo;
import cn.exploring.engine.server.db.domain.StudentPointInfo;
import cn.exploring.engine.server.db.domain.StudentPointInfoExample;
import cn.exploring.engine.server.db.domain.vo.StudentInfoExcelImportVo;
import cn.exploring.engine.server.db.domain.vo.StudentPointExcelExportVo;
import cn.exploring.engine.server.db.util.Util;
import com.alibaba.excel.EasyExcel;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.print.attribute.IntegerSyntax;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class StudentPointService {

    @Resource
    StudentPointInfoMapper studentPointInfoMapper;

    @Resource
    SpecialSqlMapper specialSqlMapper;

    @Resource
    StudentInfoService studentInfoService;

    public Map selectPointByWeb( String studentName,  String studentUniqueId, Integer classId, String startTime,  String endTime, Integer page, Integer limit,  String sort,  String order) {
        List<Map> dataList =  specialSqlMapper.selectPoint(studentName, studentUniqueId, classId, startTime, endTime, page, limit, sort, order);
        Map<String, String> countInfoData = specialSqlMapper.selectPointCount(studentName, studentUniqueId, classId, startTime, endTime);
        List<Map> targetDataList =  dataList.stream().map((Function<Map, Map>) Util::exchangeMapKeyName).collect(Collectors.toList());
        return new HashMap() {{
            put("items", targetDataList);
            put("total", StringUtils.isEmpty(countInfoData.get("count_info")) ? 0L: countInfoData.get("count_info"));
        }};
    }

    /**
     * id 检索
     * @param idList
     * @return
     */
    public List<StudentPointInfo> selectPointInfo(List<Integer> idList) {
        StudentPointInfoExample example = new StudentPointInfoExample();
        StudentPointInfoExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);
        if (idList != null && idList.size() > 0) {
            criteria.andIdIn(idList);
        }
        return studentPointInfoMapper.selectByExample(example);

    }

    public String addPoint(StudentPointInfo studentPoint) {
        LocalDateTime now = LocalDateTime.now();
        studentPoint.setRecordTime(now);
        studentPoint.setUpdateTime(now);
        studentPoint.setAddTime(now);
        studentPoint.setDeleted(false);
        studentPointInfoMapper.insertSelective(studentPoint);
        return "add OK";
    }

    public Object updatePoint(StudentPointInfo studentPoint) {
        LocalDateTime now = LocalDateTime.now();
        studentPoint.setUpdateTime(now);
        studentPointInfoMapper.updateByPrimaryKey(studentPoint);
        return "update OK";
    }

    public Object batchDeleted(List<Integer> idList) {
        List<StudentPointInfo> studentPointInfoList = selectPointInfo(idList);
        studentPointInfoList.forEach(x -> {
            x.setDeleted(null);
            updatePoint(x);
        });
        return "batch deleted OK";
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Map<Integer, List<StudentPointInfo>> selectByClassGroupByStudent(Integer classId) {
        StudentPointInfoExample.Criteria criteria = new StudentPointInfoExample().createCriteria()
                .andDeletedEqualTo(StudentPointInfo.NOT_DELETED);

        if (Objects.nonNull(classId)) {
            criteria.andClassIdEqualTo(classId);
        }

        return studentPointInfoMapper.selectByExample(criteria.example())
                .stream().collect(Collectors.groupingBy(StudentPointInfo::getStudentId, Collectors.toList()));
    }

    public Map<Integer, Integer> countByClassGroupByStudent(Integer classId) {
        return selectByClassGroupByStudent(classId).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().size()));
    }

    @Transactional(rollbackFor = Exception.class)
    public void removeAll() {
        studentPointInfoMapper.updateByExampleSelective(new StudentPointInfo(){{
            setUpdateTime(LocalDateTime.now());
            setDeleted(StudentPointInfo.IS_DELETED);
        }} , new StudentPointInfoExample().createCriteria()
                        .andDeletedEqualTo(StudentPointInfo.NOT_DELETED)
                .example());
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<StudentPointInfo> listByClassId(Integer classId) {
        return studentPointInfoMapper.selectByExample(new StudentPointInfoExample().createCriteria()
                        .andDeletedEqualTo(StudentPointInfo.NOT_DELETED)
                        .andClassIdEqualTo(classId)
                .example());
    }

    public List<StudentPointExcelExportVo> transToExcelExportVo(Collection<StudentPointInfo> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }

        Map<Integer, StudentInfo> studentInfoMap = studentInfoService.selectByPrimaryKey(list.stream().map(StudentPointInfo::getStudentId).collect(Collectors.toSet()))
                .stream().collect(Collectors.toMap(StudentInfo::getId, x -> x, (k1, k2) -> k1));

        return list.stream().map(pointInfo -> new StudentPointExcelExportVo() {{
            StudentInfo studentInfo = studentInfoMap.getOrDefault(pointInfo.getStudentId(), new StudentInfo());
            setStudentName(studentInfo.getName());
            setStudentUid(studentInfo.getStudentUniqueId());
            setScore(pointInfo.getPoint());
            setAddTime(pointInfo.getAddTime());
        }}).collect(Collectors.toList());
    }

    public File transToExcelFile(List<StudentPointExcelExportVo> voList) {
        File file = null;
        try {
            file = File.createTempFile("TMP-EXCEL-", ".xlsx");

            EasyExcel.write(file, StudentPointExcelExportVo.class).sheet().doWrite(voList);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return file;
    }


}
