package com.testor.module.train.course.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.testor.biz.file.model.domain.SysFile;
import com.testor.biz.file.service.SysFileService;
import com.testor.biz.rule.service.SysRuleService;
import com.testor.biz.sys.dict.data.controller.SysDictDataController;
import com.testor.biz.sys.org.model.domain.SysOrg;
import com.testor.biz.sys.org.service.SysOrgService;
import com.testor.common.constant.DefaultRule;
import com.testor.common.core.utils.StringUtils;
import com.testor.common.util.DateUtil;
import com.testor.module.train.course.dao.TTrainCourseDao;
import com.testor.module.train.course.model.domain.TTrainCourse;
import com.testor.module.train.course.model.domain.TTrainSection;
import com.testor.module.train.course.model.domain.TTrainSmallNode;
import com.testor.module.train.course.model.dto.TTrainCourseDelParam;
import com.testor.module.train.course.model.dto.TTrainCourseParam;
import com.testor.module.train.course.model.dto.TTrainSectionParam;
import com.testor.module.train.course.model.dto.TTrainSmallNodeParam;
import com.testor.module.train.course.service.TTrainCourseService;
import com.testor.module.train.course.service.TTrainSectionService;
import com.testor.module.train.course.service.TTrainSmallNodeService;
import com.testor.module.train.database.model.domain.TTrainDatabase;
import com.testor.module.train.database.service.TTrainDatabaseService;
import com.testor.module.train.myManagement.model.domain.TTrainCourseLearnStatistics;
import com.testor.module.train.myManagement.model.domain.TTrainMyManagement;
import com.testor.module.train.myManagement.service.TTrainCourseLearnStatisticsService;
import com.testor.module.train.myManagement.service.TTrainMyManagementService;
import com.testor.module.train.project.model.dto.MyManagement;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.biz.models.BaseResponse;
import com.tongtech.tfw.backend.common.biz.models.BizGeneralResponse;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import com.tongtech.tfw.backend.common.models.sys.UserInfo;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.TypeHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 课程管理——安全培训教育Service业务层处理
 *
 * @author testor-framework
 * @date 2022-07-25 18:06:04
 */
@Service
public class TTrainCourseServiceImpl extends SuperServiceImpl<TTrainCourseDao, TTrainCourse> implements TTrainCourseService {
    @Autowired(required = false)
    private TTrainCourseDao tTrainCourseDao;

    @Autowired
    private SysOrgService sysOrgService;

    @Autowired
    private TTrainSectionService tTrainSectionService;

    @Autowired
    private TTrainSmallNodeService tTrainSmallNodeService;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private TTrainDatabaseService tTrainDatabaseService;

    @Autowired
    private SysDictDataController sysDictDataController;

    @Autowired
    private TTrainMyManagementService tTrainMyManagementService;
    @Autowired
    private SysRuleService sysRuleService;
    @Autowired
    private TTrainCourseLearnStatisticsService tTrainCourseLearnStatisticsService;


    @Override
    public BaseResponse<TTrainCourse> addEntity(TTrainCourseParam addRequest) throws Exception {
        BaseResponse<TTrainCourse> baseResponse = new BaseResponse<>();
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (ObjectHelper.isNotEmpty(addRequest)) {
            // 存储多个章节信息
            List<TTrainSection> tTrainSectionList = new ArrayList<>();
            // 存储多个小节信息
            List<TTrainSmallNode> smallNodeArrayList = new ArrayList<>();
            String id = addRequest.getId();
            if (StringHelper.isEmpty(addRequest.getId())) {
                id = IdHelper.getId32bit();
            }else{
                // 删除原有数据
                deleteTrainCoure(id);
            }
            // 章节
            List<TTrainSectionParam> trainSectionParams = addRequest.getTrainSectionParams();
            // 校验至少有一个章节和小节
            checkoutSection(trainSectionParams);
            for (TTrainSectionParam trainSectionParam : trainSectionParams) {
                // 每一个章节
                TTrainSectionParam tTrainSection = BeanHelper.beanToBean(trainSectionParam, TTrainSectionParam.class);
                // 章节id
                String sectionId = trainSectionParam.getId();
                if (StringHelper.isEmpty(trainSectionParam.getId())) {
                    sectionId = IdHelper.getId32bit();
                }
                tTrainSection.setId(sectionId);
                // 存储课程id
                tTrainSection.setCourseId(id);
                // 章节对应的多个小节
                List<TTrainSmallNodeParam> tTrainSmallNodes = tTrainSection.getTTrainSmallNodes();
                for (TTrainSmallNode tTrainSmallNode : tTrainSmallNodes) {
                    // 小节 id
                    String smallNodeId = tTrainSmallNode.getId();
                    if (StringHelper.isEmpty(tTrainSmallNode.getId())) {
                        smallNodeId = IdHelper.getId32bit();
                    }
                    tTrainSmallNode.setId(smallNodeId);
                    // 存储章节id
                    tTrainSmallNode.setSectionId(sectionId);
                    // 存储多个小节到集合
                    smallNodeArrayList.add(tTrainSmallNode);
                }
                // 存储多个章节到集合
                tTrainSectionList.add(tTrainSection);
            }
            TTrainCourse data = BeanHelper.beanToBean(addRequest, TTrainCourse.class);
            data.setOrgId(loginUser.getOrgId());
            data.setOrgName(sysOrg.getOrgName());
            data.setOrgLevel(sysOrg.getTreeLevel().toString());
            data.setId(id);
            boolean result = false;
            // 存储课程
            result = this.saveOrUpdate(data);
            // 存储每个章节
            result = tTrainSectionService.saveOrUpdateBatch(tTrainSectionList);
            // 存储每个小节
            result = tTrainSmallNodeService.saveOrUpdateBatch(smallNodeArrayList);
            if (result) {
                TTrainCourse newEntity = new TTrainCourse();
                newEntity.setId(id);
                baseResponse.setData(newEntity);
            }
        }
        return baseResponse;
    }

    /**
     * 编辑课程，删除原有数据
     * @param id
     */
    private void deleteTrainCoure(String id) {
        // 课程对应的章节
        List<TTrainSection> sectionList = tTrainSectionService.list(new QueryWrapper<TTrainSection>().eq(TTrainSection.COURSE_ID, id));
        List<String> collect = new ArrayList<>();
        for (TTrainSection item : sectionList) {
            collect.add(item.getId());
        }
        boolean smallNodes = tTrainSmallNodeService.remove(new QueryWrapper<TTrainSmallNode>().in(TTrainSmallNode.SECTION_ID, collect));
        tTrainSectionService.remove(new QueryWrapper<TTrainSection>().in(TTrainSection.COURSE_ID,id));

    }

    /**
     * 校验至少有一个章节和小节
     *
     * @param trainSectionParams
     */
    private void checkoutSection(List<TTrainSectionParam> trainSectionParams) throws Exception {

    }

    @Override
    public BaseResponse<TTrainCourseParam> getByIds(String id) {
        BaseResponse<TTrainCourseParam> baseResponse = new BaseResponse<>();
        if (StringHelper.isNotEmpty(id)) {
            // 课程信息
            TTrainCourse data = this.getById(id);
            // 课程
            TTrainCourseParam tTrainCourseParam = BeanHelper.beanToBean(data, TTrainCourseParam.class);
            // 根据课程id查询对应章节
            List<TTrainSection> list = tTrainSectionService.list(new QueryWrapper<TTrainSection>()
                    .eq(TTrainSection.COURSE_ID, id)
                    .ne(TTrainSection.STATUS, BizConstants.STATUS_DELETE)
                    .orderByAsc(TTrainSection.SEVERAL_SECTION)
            );
            // 封装多个章节
            List<TTrainSectionParam> tTrainSectionParams = new ArrayList<>();
            for (TTrainSection tTrainSection : list) {
                TTrainSectionParam tTrainSectionParam = BeanHelper.beanToBean(tTrainSection, TTrainSectionParam.class);
                // 章节下对应的小节
                List<TTrainSmallNode> smallNodes = tTrainSmallNodeService.list(new QueryWrapper<TTrainSmallNode>()
                        .eq(TTrainSmallNode.SECTION_ID, tTrainSection.getId())
                        .ne(TTrainSmallNode.STATUS, BizConstants.STATUS_DELETE)
                        .orderByAsc(TTrainSmallNode.SEVERAL_SMALL_NODE)
                );
                // 获取资料
                List<TTrainSmallNodeParam> nodeParamList = new ArrayList<>();
                for (TTrainSmallNode smallNode : smallNodes) {
                    TTrainSmallNodeParam tTrainSmallNodeParam = BeanHelper.beanToBean(smallNode, TTrainSmallNodeParam.class);
                    // 获取资料详情
                    SysFile one = sysFileService.getOne(new QueryWrapper<SysFile>()
                            .eq(SysFile.FILE_ID, tTrainSmallNodeParam.getDataId())
                            .ne(SysFile.STATUS, BizConstants.STATUS_DELETE)
                    );
                    if (ObjectHelper.isNotEmpty(one)) {
                        tTrainSmallNodeParam.setFileName(one.getFileName());
                        tTrainSmallNodeParam.setFilePath(one.getFilePath());
                    }
                    nodeParamList.add(tTrainSmallNodeParam);
                }
                tTrainSectionParam.setTTrainSmallNodes(nodeParamList);
                tTrainSectionParams.add(tTrainSectionParam);
            }
            tTrainCourseParam.setTrainSectionParams(tTrainSectionParams);
            baseResponse.setData(tTrainCourseParam);
        }
        return baseResponse;
    }

    @Override
    public BaseResponse<BizGeneralResponse> updateEntity(TTrainCourse updateRequest) {
        BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
        if (ObjectHelper.isNotEmpty(updateRequest) && StringHelper.isNotEmpty(updateRequest.getId())) {
            TTrainCourse data = BeanHelper.beanToBean(updateRequest, TTrainCourse.class);
            boolean result = this.updateById(data);
            baseResponse.setData(
                    BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
        }
        return baseResponse;
    }

    @Override
    public BaseResponse<BizGeneralResponse> deleteEntity(TTrainCourseDelParam deleteRequest) {
        BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
        if (ObjectHelper.isNotEmpty(deleteRequest) && StringHelper.isNotEmpty(deleteRequest.getId())) {
            TTrainCourse data = new TTrainCourse();
            data.setId(deleteRequest.getId());
            data.setStatus(BizConstants.STATUS_DELETE);
            boolean result = this.updateById(data);
            if (result) {
                tTrainMyManagementService.update(new UpdateWrapper<TTrainMyManagement>().eq(TTrainMyManagement.TASK_ID, deleteRequest.getId())
                        .set(TTrainMyManagement.STATUS, BizConstants.STATUS_DELETE)
                );
            }
            baseResponse.setData(
                    BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
        }
        return baseResponse;
    }

    @Override
    public BaseResponse<List<TTrainDatabase>> selectData(String dictKey) {
        BaseResponse<List<TTrainDatabase>> listBaseResponse = new BaseResponse<>();
        String rule = sysRuleService.dataRuleScope(DefaultRule.DEPT_ALL.name());
        List<TTrainDatabase> list = tTrainDatabaseService.list(new QueryWrapper<TTrainDatabase>()
                .eq(TTrainDatabase.SECOND_SUBJECT, dictKey)
                .ne(TTrainDatabase.STATUS, BizConstants.STATUS_DELETE)
                .apply(rule)
        );
        listBaseResponse.setData(list);
        return listBaseResponse;
    }

    @Override
    public BaseResponse<List<TTrainDatabase>> fuzzySearch(String dataName) {
        BaseResponse<List<TTrainDatabase>> listBaseResponse = new BaseResponse<>();
        List<TTrainDatabase> list = tTrainDatabaseService.list(new QueryWrapper<TTrainDatabase>()
                .like(TTrainDatabase.DATA_NAME, dataName)
                .ne(TTrainDatabase.STATUS, BizConstants.STATUS_DELETE)
        );
        ArrayList<TTrainDatabase> tTrainDatabases = new ArrayList<>();
        List<TTrainDatabase> tTrainDatabases1 = converDict(list);
        for (TTrainDatabase tTrainDatabase : tTrainDatabases1) {
            TTrainDatabase tTrainDatabase1 = new TTrainDatabase();
            String data = tTrainDatabase.getStairSubject() + "-" + tTrainDatabase.getSecondSubject() + "-" + tTrainDatabase.getDataName();
            tTrainDatabase1.setDataName(data);
            tTrainDatabase1.setAttachmentId(tTrainDatabase.getAttachmentId());
            tTrainDatabases.add(tTrainDatabase1);
        }
        listBaseResponse.setData(tTrainDatabases);
        return listBaseResponse;
    }

    @Override
    public List<TTrainCourse> getCourse(String courseId) {
        String[] split = courseId.split(",");
        List<TTrainCourse> list1 = list(new QueryWrapper<TTrainCourse>()
                .in(TTrainCourse.ID, split)
        );
        return list1;
    }

    @Override
    public List<TTrainCourse> getDetailCourse(String courseId) {
        String[] split = courseId.split(",");
        List<TTrainCourse> list = this.list(new QueryWrapper<TTrainCourse>()
                .in(TTrainCourse.ID, split)
                .select(TTrainCourse.COURSE_NAME, TTrainCourse.ID)
        );
        return list;
    }

    @Override
    public void joinLearn(TTrainCourse addRequest) throws Exception {
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        // 课程id
        String id = addRequest.getId();
        TTrainCourse tTrainCourse = this.getOne(new QueryWrapper<TTrainCourse>()
                .eq(TTrainCourse.ID, id)
                .ne(TTrainCourse.STATUS, BizConstants.STATUS_DELETE)
        );
        MyManagement myManagement = new MyManagement();
        myManagement.setOrgId(loginUser.getOrgId());
        myManagement.setPersonId(loginUser.getUserId());
        myManagement.setTaskName(tTrainCourse.getCourseName());
        myManagement.setLearnWay("2");
        myManagement.setCurrentStatus("0");
        myManagement.setTabStatus("1");
        myManagement.setIsAddExam("0");
        myManagement.setTaskId(id);
        myManagement.setVisitStartTime(new Date());
        myManagement.setVisitEndTime(DateUtil.localDateTimeToDate(LocalDateTime.now().plusYears(10)));
        tTrainMyManagementService.addCourse(myManagement);
    }

    /**
     * 字典值转换
     *
     * @param baseResponseList
     * @return
     */
    private List<TTrainDatabase> converDict(List<TTrainDatabase> baseResponseList) {
        List<TTrainDatabase> data1 = new ArrayList<>();
        for (TTrainDatabase datum : baseResponseList) {
            TTrainDatabase tTrainDatabase = BeanHelper.beanToBean(datum, TTrainDatabase.class);
            String stairSubject = tTrainDatabase.getStairSubject();
            String secondSubject = tTrainDatabase.getSecondSubject();
            String subject_level = sysDictDataController.getDictTypeDetail("", "SUBJECT_LEVEL", stairSubject).getData().getDictValue();
            tTrainDatabase.setStairSubject(subject_level);
            String subject_level1 = sysDictDataController.getDictTypeDetail("", "SUBJECT_LEVEL", secondSubject).getData().getDictValue();
            tTrainDatabase.setSecondSubject(subject_level1);
            data1.add(tTrainDatabase);
        }
        return data1;
    }

    @Override
    public BaseResponse<TTrainCourseParam> getBySection(String id, String taskId) {
        BaseResponse<TTrainCourseParam> baseResponse = new BaseResponse<>();
        if (StringHelper.isNotEmpty(id)) {
            // 课程信息
            TTrainCourse data = this.getById(id);
            // 课程
            TTrainCourseParam tTrainCourseParam = BeanHelper.beanToBean(data, TTrainCourseParam.class);
            // 根据课程id查询对应章节
            List<TTrainSection> list = tTrainSectionService.list(new QueryWrapper<TTrainSection>()
                    .eq(TTrainSection.COURSE_ID, id).orderByAsc("several_section")
            );
            // 封装多个章节
            List<TTrainSectionParam> tTrainSectionParams = new ArrayList<>();
            for (TTrainSection tTrainSection : list) {
                TTrainSectionParam tTrainSectionParam = BeanHelper.beanToBean(tTrainSection, TTrainSectionParam.class);
                // 章节下对应的小节
                List<TTrainSmallNode> smallNodes = tTrainSmallNodeService.list(new QueryWrapper<TTrainSmallNode>()
                        .eq(TTrainSmallNode.SECTION_ID, tTrainSection.getId()).orderByAsc("several_small_node")
                );
                String sectionPlan = "0";
                // 获取资料
                List<TTrainSmallNodeParam> nodeParamList = new ArrayList<>();
                for (TTrainSmallNode smallNode : smallNodes) {

                    TTrainSmallNodeParam tTrainSmallNodeParam = BeanHelper.beanToBean(smallNode, TTrainSmallNodeParam.class);
                    // 获取资料详情
                    SysFile one = sysFileService.getOne(new QueryWrapper<SysFile>()
                            .eq(SysFile.FILE_ID, tTrainSmallNodeParam.getDataId())
                    );
                    if (ObjectHelper.isNotEmpty(one)) {
                        tTrainSmallNodeParam.setFileName(one.getFileName());
                        tTrainSmallNodeParam.setFilePath(one.getFilePath());
                    }
                    TTrainCourseLearnStatistics learnStatistics = findPlanProgress(taskId, id, tTrainSection.getId(), smallNode.getId());
                    if (ObjectHelper.isNotEmpty(learnStatistics)) {
                        tTrainSmallNodeParam.setSmallPlan(learnStatistics.getSmallPlan());
                        String sectionPlanOne = learnStatistics.getSectionPlan();
                        if (StringUtils.isNotBlank(sectionPlanOne) && Integer.parseInt(sectionPlanOne)>Integer.parseInt(sectionPlan)) {
                            sectionPlan = learnStatistics.getSectionPlan();
                        }
                    }
                    nodeParamList.add(tTrainSmallNodeParam);
                }
                tTrainSectionParam.setTTrainSmallNodes(nodeParamList);
                tTrainSectionParam.setSectionPlan(sectionPlan);
                tTrainSectionParams.add(tTrainSectionParam);
            }
            tTrainCourseParam.setTrainSectionParams(tTrainSectionParams);
            baseResponse.setData(tTrainCourseParam);
        }
        return baseResponse;

    }

    private TTrainCourseLearnStatistics findPlanProgress(String taskId, String courseId, String sectionId, String smallNodeId){
        return tTrainCourseLearnStatisticsService.lambdaQuery()
                .eq(TTrainCourseLearnStatistics::getTaskId, taskId)
                .eq(TTrainCourseLearnStatistics::getCourseId, courseId)
                .eq(TTrainCourseLearnStatistics::getSectionId, sectionId)
                .eq(TTrainCourseLearnStatistics::getSmallNodeId, smallNodeId)
                .orderByDesc(TTrainCourseLearnStatistics::getSmallPlan)
                .last("limit 1").one();

    }



}
