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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.entity.TBSyncTask;
import com.qmth.distributed.print.business.mapper.TBSyncTaskMapper;
import com.qmth.distributed.print.business.service.*;
import com.qmth.distributed.print.business.templete.execute.AsyncCloudMarkingTaskService;
import com.qmth.distributed.print.business.templete.execute.AsyncTeachCloudReportService;
import com.qmth.teachcloud.common.bean.params.UserPushParam;
import com.qmth.teachcloud.common.bean.result.SyncListResult;
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.PushTypeEnum;
import com.qmth.teachcloud.common.enums.TaskResultEnum;
import com.qmth.teachcloud.common.enums.TaskStatusEnum;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @Date: 2021/5/20.
 */
@Service
public class TBSyncTaskServiceImpl extends ServiceImpl<TBSyncTaskMapper, TBSyncTask> implements TBSyncTaskService {

    @Resource
    AsyncCloudMarkingTaskService asyncCloudMarkingTaskService;

    @Resource
    ExamPaperStructureService examPaperStructureService;

    @Resource
    ExamPrintPlanService examPrintPlanService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    AsyncTeachCloudReportService asyncTeachCloudReportService;

    @Resource
    GradeBatchService gradeBatchService;

    @Resource
    GradeBatchPaperService gradeBatchPaperService;

    @Resource
    CloudUserPushService cloudUserPushService;

    @Resource
    SysUserService sysUserService;

    @Transactional
    @Override
    public TBSyncTask saveTask(Long schoolId, Long objectId, PushTypeEnum type) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        QueryWrapper<TBSyncTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TBSyncTask::getSchoolId, schoolId)
                .eq(TBSyncTask::getObjectId, objectId)
                .eq(TBSyncTask::getType, type);
        TBSyncTask tbSyncTask = this.getOne(queryWrapper);
        Long id = SystemConstant.getDbUuid();
        if (tbSyncTask != null) {
            if (!TaskStatusEnum.FINISH.equals(tbSyncTask.getStatus())) {
                throw ExceptionResultEnum.ERROR.exception("有任务未结束");
            }
            id = tbSyncTask.getId();
            this.removeById(id);
        }
        tbSyncTask = new TBSyncTask();
        tbSyncTask.setId(id);
        tbSyncTask.setSchoolId(schoolId);
        tbSyncTask.setObjectId(objectId);
        tbSyncTask.setType(type);
        tbSyncTask.setStatus(TaskStatusEnum.INIT);
        tbSyncTask.setCreateId(sysUser.getId());
        tbSyncTask.setCreateTime(System.currentTimeMillis());
        this.save(tbSyncTask);
        return tbSyncTask;
    }

    @Override
    public void updateStatusAndResultById(Long id, Long thirdRelateId, TaskStatusEnum status, TaskResultEnum result, String errorMessage) {
        UpdateWrapper<TBSyncTask> tbSyncTaskUpdateWrapper = new UpdateWrapper<>();
        tbSyncTaskUpdateWrapper.lambda().set(TBSyncTask::getStatus, status)
                .set(TBSyncTask::getThirdRelateId, thirdRelateId)
                .set(TBSyncTask::getResult, result)
                .set(TBSyncTask::getErrorMessage, errorMessage)
                .eq(TBSyncTask::getId, id);
        this.update(tbSyncTaskUpdateWrapper);
    }

    @Override
    public void updateStatusAndResultById(Long id, Long thirdRelateId, TaskStatusEnum status, TaskResultEnum result, String errorMessage, String remark) {
        UpdateWrapper<TBSyncTask> tbSyncTaskUpdateWrapper = new UpdateWrapper<>();
        tbSyncTaskUpdateWrapper.lambda().set(TBSyncTask::getStatus, status)
                .set(TBSyncTask::getThirdRelateId, thirdRelateId)
                .set(TBSyncTask::getResult, result)
                .set(TBSyncTask::getErrorMessage, errorMessage)
                .set(TBSyncTask::getRemark, remark)
                .eq(TBSyncTask::getId, id);
        this.update(tbSyncTaskUpdateWrapper);
    }

    @Transactional
    @Override
    public TBSyncTask savePushCommon(PushTypeEnum pushTypeEnum, Map map, SysUser sysUser) {
        SysUser requestUser = Objects.nonNull(sysUser) ? sysUser : (SysUser) ServletUtil.getRequestUser();
        TBSyncTask tbSyncTask = new TBSyncTask(pushTypeEnum,
                TaskStatusEnum.INIT,
                requestUser.getId(),
                requestUser.getSchoolId());

        map.computeIfAbsent(SystemConstant.TB_SYNC_TASK, v -> tbSyncTask);
        map.computeIfAbsent(SystemConstant.USER, v -> requestUser);
        map.computeIfAbsent(SystemConstant.TB_SYNC_TASK_ID, v -> tbSyncTask.getId());
        return tbSyncTask;
    }

    @Transactional
    @Override
    public TBSyncTask savePushCommon(PushTypeEnum pushTypeEnum, Map map, SysUser sysUser, Long objectId) {
        SysUser requestUser = Objects.nonNull(sysUser) ? sysUser : (SysUser) ServletUtil.getRequestUser();
        TBSyncTask tbSyncTask = new TBSyncTask(pushTypeEnum,
                TaskStatusEnum.INIT,
                requestUser.getId(),
                requestUser.getSchoolId(),
                objectId);

        map.computeIfAbsent(SystemConstant.TB_SYNC_TASK, v -> tbSyncTask);
        map.computeIfAbsent(SystemConstant.USER, v -> requestUser);
        map.computeIfAbsent(SystemConstant.TB_SYNC_TASK_ID, v -> tbSyncTask.getId());
        return tbSyncTask;
    }

    @Override
    public IPage<SyncListResult> query(Long schoolId, TaskStatusEnum status, PushTypeEnum type, TaskResultEnum result, int pageNumber, int pageSize) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);

        IPage<SyncListResult> page = this.baseMapper.query(new Page<>(pageNumber, pageSize), schoolId, status, type, result, sysUser.getId(), orgIds);
        List<SyncListResult> list = page.getRecords();
        for (SyncListResult syncListResult : list) {
            syncListResult.setStatus(Objects.nonNull(syncListResult.getStatus()) ? TaskStatusEnum.valueOf(syncListResult.getStatus()).getTitle() : null);
            syncListResult.setType(Objects.nonNull(syncListResult.getType()) ? PushTypeEnum.valueOf(syncListResult.getType()).getTitle() : null);
            syncListResult.setResultStr(Objects.nonNull(syncListResult.getResult()) ? TaskResultEnum.valueOf(syncListResult.getResult()).getTitle() : null);
        }
        return page;
    }

    @Override
    public TBSyncTask findUserPushRecord(Long userId, Long schoolId) {
        List<TBSyncTask> userPushList = this.list(new QueryWrapper<TBSyncTask>()
                .lambda()
                .eq(TBSyncTask::getSchoolId, schoolId)
                .eq(TBSyncTask::getObjectId, userId)
                .eq(TBSyncTask::getType, PushTypeEnum.USER_PUSH));
        if (userPushList != null && userPushList.size() > 0) {
            if (userPushList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception("异常：用户【" + userId + "】拥有多条推送记录");
            }
            return userPushList.get(0);
        } else {
            return null;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void initUserPushTasks(Map<Long, List<UserPushParam>> userPushMap, SysUser requestUser) {
        Long schoolId = requestUser.getSchoolId();
        for (Long userId : userPushMap.keySet()) {
            TBSyncTask dbRecord = this.findUserPushRecord(userId, schoolId);
            Long id;
            if (Objects.nonNull(dbRecord)) {
                id = dbRecord.getId();
            } else {
                id = SystemConstant.getDbUuid();
            }
            TBSyncTask tbSyncTask = new TBSyncTask();
            tbSyncTask.setId(id);
            tbSyncTask.setSchoolId(schoolId);
            tbSyncTask.setType(PushTypeEnum.USER_PUSH);
            tbSyncTask.setObjectId(userId);
            tbSyncTask.setStatus(TaskStatusEnum.INIT);
            tbSyncTask.setRemark(sysUserService.getById(userId).getLoginName());
            tbSyncTask.setResult(null);
            tbSyncTask.setCreateId(requestUser.getId());
            tbSyncTask.setCreateTime(System.currentTimeMillis());
            this.saveOrUpdate(tbSyncTask);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TBSyncTask runningUserPushTask(Long userId, SysUser requestUser) {
        Long schoolId = requestUser.getSchoolId();
        TBSyncTask tbSyncTask = this.findUserPushRecord(userId, schoolId);
        if (Objects.isNull(tbSyncTask)) {
            throw ExceptionResultEnum.ERROR.exception("用户推送表信息缺失");
        }
        tbSyncTask.setStatus(TaskStatusEnum.RUNNING);
        tbSyncTask.updateInfo(requestUser.getId());
        this.saveOrUpdate(tbSyncTask);
        return tbSyncTask;
    }

    @Override
    public void resync(Long id) throws IllegalAccessException {
        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
        TBSyncTask tbSyncTask = this.getById(id);
        if (tbSyncTask == null) {
            throw ExceptionResultEnum.ERROR.exception("任务不存在");
        }
        if (!TaskStatusEnum.FINISH.equals(tbSyncTask.getStatus())) {
            throw ExceptionResultEnum.ERROR.exception("任务同步中");
        }
        if (TaskResultEnum.SUCCESS.equals(tbSyncTask.getResult())) {
            throw ExceptionResultEnum.ERROR.exception("任务同步成功");
        }
        switch (tbSyncTask.getType()) {
            case EXAM_PUSH:
                asyncCloudMarkingTaskService.syncExamAndStudentAndCard(examPrintPlanService.getById(tbSyncTask.getObjectId()), tbSyncTask.getThirdRelateId(), null);
                break;
            case STRUCTURE_GROUP_PUSH:
                asyncCloudMarkingTaskService.syncPaperStructureAndGroup(examPaperStructureService.getById(tbSyncTask.getObjectId()));
                break;
            case PAPER_ANSWER_FILE_PUSH:
                asyncCloudMarkingTaskService.syncPaperAndAnswer(examPaperStructureService.getById(tbSyncTask.getObjectId()));
                break;
            case OBJECTIVE_ANSWER_PUSH:
                asyncCloudMarkingTaskService.syncObjectiveStructure(examPaperStructureService.getById(tbSyncTask.getObjectId()));
                break;
            case GRADE_BATCH_PUSH:
                asyncTeachCloudReportService.syncGradeBatch(gradeBatchService.getById(tbSyncTask.getObjectId()));
                break;
            case PUBLISH:
                asyncTeachCloudReportService.publish(gradeBatchPaperService.getById(tbSyncTask.getObjectId()));
                break;
            case CALCULATE:
                asyncTeachCloudReportService.startCalc(gradeBatchService.getById(tbSyncTask.getObjectId()));
                break;
            case USER_PUSH:
                cloudUserPushService.pushCloudUser(tbSyncTask.getObjectId(), requestUser);
                break;
            default:
                break;
        }
    }
}
