package com.qmth.teachcloud.mark.service.impl;

import java.util.List;

import javax.annotation.Resource;

import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import org.springframework.stereotype.Service;

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.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.mark.MarkProblemStatus;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.util.ServletUtil;
import com.qmth.teachcloud.mark.dto.mark.manage.MarkProblemDto;
import com.qmth.teachcloud.mark.entity.MarkProblemHistory;
import com.qmth.teachcloud.mark.entity.MarkStudent;
import com.qmth.teachcloud.mark.entity.MarkTask;
import com.qmth.teachcloud.mark.enums.LockType;
import com.qmth.teachcloud.mark.enums.MarkTaskStatus;
import com.qmth.teachcloud.mark.lock.LockService;
import com.qmth.teachcloud.mark.mapper.MarkProblemHistoryMapper;
import com.qmth.teachcloud.mark.service.MarkProblemHistoryService;
import com.qmth.teachcloud.mark.service.MarkQuestionService;
import com.qmth.teachcloud.mark.service.MarkService;
import com.qmth.teachcloud.mark.service.MarkStudentService;
import com.qmth.teachcloud.mark.service.MarkTaskService;

/**
 * <p>
 * 问题卷历史表 服务实现类
 * </p>
 *
 * @author xf
 * @since 2023-09-22
 */
@Service
public class MarkProblemHistoryServiceImpl extends ServiceImpl<MarkProblemHistoryMapper, MarkProblemHistory>
		implements MarkProblemHistoryService {

	@Resource
	private MarkStudentService markStudentService;
	@Resource
	private MarkQuestionService markQuestionService;
	@Resource
	private SysUserService sysUserService;
	@Resource
	private MarkTaskService markTaskService;
	@Resource
	private TeachcloudCommonService teachcloudCommonService;
	@Resource
	private MarkService markService;
	@Resource
	private LockService lockService;

	@Override
	public IPage<MarkProblemDto> pageProblem(Long examId, String paperNumber, Integer groupNumber, String problemType,
			String status, String secretNumber, Integer pageNumber, Integer pageSize) {
		Page<MarkProblemDto> page = new Page<>(pageNumber, pageSize);
		IPage<MarkProblemDto> markProblemDtoIPage = this.baseMapper.pageProblem(page, examId, paperNumber, groupNumber,
				problemType, status, secretNumber);
		for (MarkProblemDto problemDto : markProblemDtoIPage.getRecords()) {
			MarkStudent markStudent = markStudentService.getById(problemDto.getStudentId());
			problemDto.setStudentName(markStudent.getStudentName());
			problemDto.setStudentCode(markStudent.getStudentCode());
			problemDto.setSheetUrls(teachcloudCommonService.filePreview(markStudent.getSheetPathList()));
			problemDto.setProblemTypeName(problemDto.getType().getDesc());
			problemDto.setStatusName(problemDto.getStatus().getName());
			problemDto.setGroupQuestions(markQuestionService
					.assembleGroupQuestionsByExamIdAndPaperNumberAndNumber(examId, paperNumber, problemDto.getGroupNumber()));
			if (problemDto.getUserId() != null) {
				SysUser sysUser = sysUserService.getById(problemDto.getUserId());
				if (sysUser != null) {
					problemDto.setUserLoginName(sysUser.getLoginName());
					problemDto.setUserName(sysUser.getRealName());
				}
			}
			if (problemDto.getUpdateUserId() != null) {
				SysUser sysUser = sysUserService.getById(problemDto.getUpdateUserId());
				if (sysUser != null) {
					problemDto.setUpdateUserLoginName(sysUser.getLoginName());
					problemDto.setUpdateUserName(sysUser.getRealName());
				}
			}
		}
		return markProblemDtoIPage;
	}

	@Override
	public void resetProblem(List<Long> ids) {
		SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
		for (Long id : ids) {
			MarkProblemHistory markProblemHistory = this.getById(id);
			MarkTask markTask = markTaskService.getById(markProblemHistory.getTaskId());
			if (markTask != null) {
				try {
					lockService.watch(LockType.EXAM_SUBJECT, markTask.getExamId(), markTask.getPaperNumber());
					lockService.watch(LockType.GROUP, markTask.getExamId(), markTask.getPaperNumber(),
							markTask.getGroupNumber());
					if (markTask.getStatus().equals(MarkTaskStatus.PROBLEM)) {
						markService.rejectMarkTask(markProblemHistory, markTask, sysUser.getId());
					}
				} catch (Exception e) {
					log.error("back library error", e);
				} finally {
					lockService.unwatch(LockType.GROUP, markTask.getExamId(), markTask.getPaperNumber(),
							markTask.getGroupNumber());
					lockService.unwatch(LockType.EXAM_SUBJECT, markTask.getExamId(), markTask.getPaperNumber());
				}
			}
		}

	}

	@Override
	public void resetByMarkProblemId(Long id, MarkProblemStatus waiting, Long userId, MarkProblemStatus back, Long now) {
		UpdateWrapper<MarkProblemHistory> updateWrapper = new UpdateWrapper<>();
		updateWrapper.lambda().set(MarkProblemHistory::getUpdateUserId, userId).set(MarkProblemHistory::getStatus, back)
				.set(MarkProblemHistory::getUpdateTime, now).eq(MarkProblemHistory::getId, id)
				.eq(MarkProblemHistory::getStatus, waiting);
		this.update(updateWrapper);
	}

	@Override
	public void deleteByStudentId(Long studentId) {
		UpdateWrapper<MarkProblemHistory> updateWrapper = new UpdateWrapper<>();
		updateWrapper.lambda().eq(MarkProblemHistory::getStudentId, studentId);
		this.remove(updateWrapper);
	}

	@Override
	public void deleteByExamIdAndPaperNumberAndGroupNumber(Long examId, String paperNumber, Integer groupNumber) {
		UpdateWrapper<MarkProblemHistory> updateWrapper = new UpdateWrapper<>();
		updateWrapper.lambda().eq(MarkProblemHistory::getExamId, examId)
				.eq(MarkProblemHistory::getPaperNumber, paperNumber)
				.eq(MarkProblemHistory::getGroupNumber, groupNumber);
		this.remove(updateWrapper);
	}

	@Override
	public MarkProblemHistory findByTaskIdAndStatus(Long taskId, MarkProblemStatus status) {
		QueryWrapper<MarkProblemHistory> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(MarkProblemHistory::getTaskId, taskId).eq(MarkProblemHistory::getStatus, status);
		return this.getOne(queryWrapper);
	}
}
