package cn.com.qmth.examcloud.core.questions.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.basic.api.CourseCloudService;
import cn.com.qmth.examcloud.core.basic.api.bean.CourseBean;
import cn.com.qmth.examcloud.core.basic.api.request.GetCourseByOrgReq;
import cn.com.qmth.examcloud.core.basic.api.response.GetCourseByOrgResp;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
import cn.com.qmth.examcloud.core.questions.dao.QuesTypeNameRepo;
import cn.com.qmth.examcloud.core.questions.dao.QuestionAudioRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesTypeName;
import cn.com.qmth.examcloud.core.questions.service.CopyDataService;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataDto;
import cn.com.qmth.examcloud.core.questions.service.bean.CopyDataNoReduplicateDto;
import cn.com.qmth.examcloud.core.questions.service.producer.CopyDataNoReduplicateProducer;
import cn.com.qmth.examcloud.core.questions.service.producer.CopyDataProducer;
import cn.com.qmth.examcloud.web.redis.RedisClient;

@Service("copyDataService")
public class CopyDataServiceImpl implements CopyDataService {
	private static final Logger log = LoggerFactory.getLogger(CopyDataService.class);
	private static int cacheLockTimeout = 60 * 10;
	private static String withoutReduplicateLock = "$_COPY_QUESTION_DATA_NO_REDUPLICATE_LOCK";
	@Autowired
	private CourseCloudService courseCloudService;

	@Autowired
	private PaperRepo paperRepo;

	@Autowired
	private CopyDataProducer copyDataProducer;
	
	@Autowired
	private CopyDataNoReduplicateProducer copyDataNoReduplicateProducer;

	@Autowired
	private PaperDetailRepo paperDetailRepo;

	@Autowired
	private PaperDetailUnitRepo paperDetailUnitRepo;

	@Autowired
	private PaperService paperService;

	@Autowired
	private QuesRepo quesRepo;
	@Autowired
	private QuesTypeNameRepo quesTypeNameRepo;
	@Autowired
	private QuestionAudioRepo questionAudioRepo;

	@Autowired
	private RedisClient redisClient;

	@Async
	@Override
	@Transactional
	public void copyNoReduplicate(User user, String batch) {
		Long rootOrgId = user.getRootOrgId();
		boolean sucss = true;
		long s1 = System.currentTimeMillis();
		try {
			log.warn("数据复制开始 | rootOrgId=" + rootOrgId);
			disposeCopyNoReduplicate(user, batch);
		} catch (Exception e) {
			sucss = false;
			throw e;
		} finally {
			long s2 = System.currentTimeMillis();
			if (sucss) {
				log.warn("数据复制结束 | 成功 |  " + ((s2 - s1) / 1000) + "秒 |  rootOrgId=" + rootOrgId);
			} else {
				log.warn("数据复制结束 | 失败 |  " + ((s2 - s1) / 1000) + "秒 |  rootOrgId=" + rootOrgId);
			}
			redisClient.delete(withoutReduplicateLock);
		}
	}

	private void disposeCopyNoReduplicate(User user, String batch) {
		Long rootOrgId=user.getRootOrgId();
		redisClient.expire(withoutReduplicateLock, cacheLockTimeout);
		List<CourseBean> courses = new ArrayList<>();
		GetCourseByOrgReq courseReq = new GetCourseByOrgReq();
		courseReq.setRootOrgId(rootOrgId);
		GetCourseByOrgResp res = courseCloudService.getCourseByOrg(courseReq);
		if (CollectionUtils.isEmpty(res.getCourseList())) {
			log.warn("没有课程数据");
		}
		for (CourseBean c : res.getCourseList()) {
			if (c.getEnable()) {
				courses.add(c);
			}
		}
		if (courses.size() == 0) {
			log.warn("没有课程数据");
		}
		redisClient.expire(withoutReduplicateLock, cacheLockTimeout);
		List<CopyDataNoReduplicateDto> dtos = new ArrayList<>();
		for (CourseBean c : courses) {
			dtos.add(new CopyDataNoReduplicateDto(c, user,batch));
		}
		Map<String, Object> param = new HashMap<>();
		param.put("dtos", dtos);
		copyDataNoReduplicateProducer.startDispose(4, param, dtos.size());
		String countInfo = "成功科目数:" + copyDataNoReduplicateProducer.getProcess() + " 科目总数:" + copyDataNoReduplicateProducer.getTotal();
		log.warn(countInfo);
	}

	@Override
	@Transactional
	public void copyData(User user, Long fromRootOrgId, Long toRootOrgId) {
		boolean sucss = true;
		long s1 = System.currentTimeMillis();
		try {
			log.warn("数据复制开始 | fromRootOrgId=" + fromRootOrgId + " | toRootOrgId=" + toRootOrgId);
			dispose(user, fromRootOrgId, toRootOrgId);
		} catch (Exception e) {
			sucss = false;
			throw e;
		} finally {
			long s2 = System.currentTimeMillis();
			if (sucss) {
				log.warn("数据复制结束 | 成功 |  " + ((s2 - s1) / 1000) + "秒 |  fromRootOrgId=" + fromRootOrgId
						+ " | toRootOrgId=" + toRootOrgId);
			} else {
				log.warn("数据复制结束 | 失败 |  " + ((s2 - s1) / 1000) + "秒 |  fromRootOrgId=" + fromRootOrgId
						+ " | toRootOrgId=" + toRootOrgId);
			}
			String cacheLock = "$_COPY_QUESTION_DATA_LOCK";
			redisClient.delete(cacheLock);
		}
	}

	private void dispose(User user, Long fromRootOrgId, Long toRootOrgId) {
		clearData(toRootOrgId);
		redisClient.expire("$_COPY_QUESTION_DATA_LOCK", cacheLockTimeout);
		Map<String, Long> courses = new HashMap<>();
		GetCourseByOrgReq courseReq = new GetCourseByOrgReq();
		courseReq.setRootOrgId(toRootOrgId);
		GetCourseByOrgResp res = courseCloudService.getCourseByOrg(courseReq);
		if (CollectionUtils.isEmpty(res.getCourseList())) {
			throw new StatusException("请先导入课程");
		}
		for (CourseBean c : res.getCourseList()) {
			courses.put(c.getCode(), c.getId());
		}
		copyQuesTypeName(courses, fromRootOrgId, toRootOrgId);
		redisClient.expire("$_COPY_QUESTION_DATA_LOCK", cacheLockTimeout);
		List<String> paperIds = paperService.findPaperId(fromRootOrgId);
		if (CollectionUtils.isNotEmpty(paperIds)) {
			List<CopyDataDto> dtos = new ArrayList<>();
			for (String paperId : paperIds) {
				dtos.add(new CopyDataDto(courses, paperId, toRootOrgId, user));
			}
			Map<String, Object> param = new HashMap<>();
			param.put("dtos", dtos);
			copyDataProducer.startDispose(8, param, dtos.size());
			String countInfo = "成功数:" + copyDataProducer.getProcess() + " 总数:" + copyDataProducer.getTotal();
			log.warn(countInfo);
		} else {
			log.warn("没有试卷数据需要处理");
		}
	}

	private void copyQuesTypeName(Map<String, Long> courses, Long fromRootOrgId, Long toRootOrgId) {
		List<QuesTypeName> cps = quesTypeNameRepo.findByOrgId(fromRootOrgId);
		if (CollectionUtils.isNotEmpty(cps)) {
			for (QuesTypeName cp : cps) {
				cp.setOrgId(toRootOrgId.toString());
				cp.setId(null);
			}
		}
		quesTypeNameRepo.saveAll(cps);
	}

	private void clearData(Long toRootOrgId) {
		quesTypeNameRepo.deleteByOrgId(toRootOrgId.toString());
		paperRepo.deleteByOrgId(toRootOrgId.toString());
		paperDetailRepo.deleteByOrgId(toRootOrgId);
		paperDetailUnitRepo.deleteByOrgId(toRootOrgId);
		quesRepo.deleteByOrgId(toRootOrgId.toString());
		questionAudioRepo.deleteByOrgId(toRootOrgId);
	}
}
