package com.xjrsoft.module.banding.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.enums.DeleteMark;
import com.xjrsoft.common.enums.YesOrNoEnum;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.banding.dto.BandingTaskClassPageDto;
import com.xjrsoft.module.banding.dto.BandingTaskClassStudentPageDto;
import com.xjrsoft.module.banding.entity.BandingTask;
import com.xjrsoft.module.banding.entity.BandingTaskClass;
import com.xjrsoft.module.banding.entity.BandingTaskClassStudent;
import com.xjrsoft.module.banding.mapper.BandingTaskClassMapper;
import com.xjrsoft.module.banding.mapper.BandingTaskClassStudentMapper;
import com.xjrsoft.module.banding.mapper.BandingTaskMapper;
import com.xjrsoft.module.banding.service.IBandingTaskClassService;
import com.xjrsoft.module.banding.vo.BandingTaskClassPageVo;
import com.xjrsoft.module.banding.vo.BandingTaskClassStudentListVo;
import com.xjrsoft.module.banding.vo.BandingTaskClassSureListVo;
import com.xjrsoft.module.base.entity.BaseClassroom;
import com.xjrsoft.module.base.entity.BaseMajorSet;
import com.xjrsoft.module.base.service.IBaseClassroomService;
import com.xjrsoft.module.base.service.IBaseMajorSetService;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.organization.service.IUserService;
import com.xjrsoft.module.system.entity.DictionaryDetail;
import com.xjrsoft.module.system.entity.DictionaryItem;
import com.xjrsoft.module.system.mapper.DictionarydetailMapper;
import com.xjrsoft.module.teacher.entity.BaseTeacher;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @title: 新生分班任务
* @Author dzx
* @Date: 2024-07-01
* @Version 1.0
*/
@Service
@AllArgsConstructor
public class BandingTaskClassServiceImpl extends MPJBaseServiceImpl<BandingTaskClassMapper, BandingTaskClass> implements IBandingTaskClassService {

    private final BandingTaskMapper bandingTaskMapper;
    private final BandingTaskClassStudentMapper classStudentMapper;
    private final IBaseClassroomService classroomService;
    private final IUserService userService;
    private final IBaseMajorSetService majorSetService;
    private final DictionarydetailMapper detailMapper;
    @Override
    public Boolean add(BandingTaskClass bandingTaskClass) {
        bandingTaskClass.setCreateDate(new Date());
        this.baseMapper.insert(bandingTaskClass);
        return true;
    }

    @Override
    public Boolean update(BandingTaskClass bandingTaskClass) {
        bandingTaskClass.setModifyDate(new Date());
        this.baseMapper.updateById(bandingTaskClass);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(List<Long> ids) {
        this.baseMapper.deleteBatchIds(ids);
        return true;
    }

    @Override
    public List<BandingTaskClassPageVo> getList(BandingTaskClassPageDto dto) {
        BandingTask bandingTask = bandingTaskMapper.selectById(dto.getBandingTaskId());
        dto.setGradeId(bandingTask.getGradeId());
        dto.setEnrollType(bandingTask.getEnrollType());
        return this.baseMapper.getList(dto);
    }

    @Override
    public Boolean reset(Long bandingTaskId) {
        List<BandingTaskClass> classList = this.baseMapper.selectList(
                new QueryWrapper<BandingTaskClass>().lambda()
                        .eq(BandingTaskClass::getBandingTaskId, bandingTaskId)
        );

        for (BandingTaskClass bandingTaskClass : classList) {
            bandingTaskClass.setModifyDate(new Date());
            bandingTaskClass.setHeight(null);
            bandingTaskClass.setScore(null);
            this.baseMapper.updateById(bandingTaskClass);
        }

        List<Long> classIds = classList.stream().map(BandingTaskClass::getId).collect(Collectors.toList());
        if(!classIds.isEmpty()){
            classStudentMapper.delete(
                    new QueryWrapper<BandingTaskClassStudent>().lambda()
                            .in(BandingTaskClassStudent::getBandingTaskClassId, classIds)
            );
        }
        return true;
    }

    @Override
    public List<BandingTaskClassStudentListVo> classStudent(BandingTaskClassStudentPageDto dto) {
        BandingTask bandingTask = bandingTaskMapper.selectById(dto.getBandingTaskId());
        dto.setGradeId(bandingTask.getGradeId());
        dto.setEnrollType(bandingTask.getEnrollType());
        return this.baseMapper.getClassStudent(dto);
    }

    @Override
    public List<BandingTaskClassSureListVo> getClassSure(BandingTaskClassStudentPageDto dto) {
        return this.baseMapper.getClassSure(dto);
    }

    @Override
    public Boolean importData(Long bandingTaskId, List<Map<Integer, Object>> excelDataList) {
        List<BaseClassroom> classroomList = classroomService.list(
                new QueryWrapper<BaseClassroom>().lambda()
                        .eq(BaseClassroom::getDeleteMark, DeleteMark.NODELETE.getCode())
        );
        Map<String, Long> classroomMap = new HashMap<>();
        for (BaseClassroom classroom : classroomList) {
            classroomMap.put(classroom.getName(), classroom.getId());
        }
        List<User> userList = userService.list(
                new MPJLambdaWrapper<User>()
                        .select(User::getId)
                        .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty()))
                        .innerJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
        );
        Map<String, Long> userMap = new HashMap<>();
        for (User user : userList) {
            userMap.put(user.getName(), user.getId());
        }

        List<BaseMajorSet> majorSetList = majorSetService.list(
                new QueryWrapper<BaseMajorSet>().lambda()
        );

        Map<String, Long> majorSetMap = new HashMap<>();
        for (BaseMajorSet majorSet : majorSetList) {
            majorSetMap.put(majorSet.getName(), majorSet.getId());
        }
        List<DictionaryDetail> classType = detailMapper.selectJoinList(DictionaryDetail.class,
                new MPJLambdaWrapper<DictionaryDetail>()
                        .select(DictionaryDetail::getId)
                        .select(DictionaryDetail.class, x -> VoToColumnUtil.fieldsToColumns(DictionaryDetail.class).contains(x.getProperty()))
                        .innerJoin(DictionaryItem.class, DictionaryItem::getId, DictionaryDetail::getItemId)
                        .eq(DictionaryItem::getCode, "class_type")
        );
        Map<String, String> classTypeMap = classType.stream().collect(Collectors.toMap(DictionaryDetail::getName, DictionaryDetail::getCode));
        List<BandingTaskClass> classList = new ArrayList<>();
        Date createDate = new Date();
        for (Map<Integer, Object> taskClass : excelDataList) {
            classList.add(new BandingTaskClass(){{
                setBandingTaskId(bandingTaskId);
                setCreateDate(createDate);
                setName(taskClass.get(1).toString());
                setMajorSetId(majorSetMap.get(taskClass.get(0).toString().trim()));
                setNumber(Integer.parseInt(taskClass.get(2).toString()));
                setClassroomId(classroomMap.get(taskClass.get(4).toString()));
                if(taskClass.get(5) != null){
                    setClassType(classTypeMap.get(taskClass.get(5).toString()));
                }
                if(taskClass.get(6) != null){
                    setIsOrderClass(YesOrNoEnum.getCode(taskClass.get(6).toString()));
                }
                if(taskClass.get(7) != null){
                    setSortCode(Integer.parseInt(taskClass.get(7).toString()));
                }
                setTeacherId(userMap.get(taskClass.get(3).toString()));
            }});
        }
        Boolean result = this.saveBatch(classList);
        return result;
    }
}
