package com.keao.edu.user.service.impl;

import com.keao.edu.auth.api.client.SysMessageFeignService;
import com.keao.edu.auth.api.client.SysUserFeignService;
import com.keao.edu.auth.api.entity.SysMessageParams;
import com.keao.edu.auth.api.entity.SysUser;
import com.keao.edu.common.dal.BaseDAO;
import com.keao.edu.common.entity.SysConfig;
import com.keao.edu.common.enums.MessageTypeEnum;
import com.keao.edu.common.exception.BizException;
import com.keao.edu.common.page.PageInfo;
import com.keao.edu.common.page.QueryInfo;
import com.keao.edu.common.service.impl.BaseServiceImpl;
import com.keao.edu.common.tenant.TenantContextHolder;
import com.keao.edu.thirdparty.message.MessageSenderPluginContext;
import com.keao.edu.user.dao.ExamOrganizationRelationDao;
import com.keao.edu.user.dao.ExaminationBasicDao;
import com.keao.edu.user.dao.TeacherDao;
import com.keao.edu.user.entity.ExamOrganizationRelation;
import com.keao.edu.user.entity.ExaminationBasic;
import com.keao.edu.user.entity.Organization;
import com.keao.edu.user.enums.ExamStatusEnum;
import com.keao.edu.user.enums.YesOrNoEnum;
import com.keao.edu.user.page.ExamOrganizationRelationQueryInfo;
import com.keao.edu.user.service.ExamOrganizationRelationService;
import com.keao.edu.user.service.OrganizationService;
import com.keao.edu.user.service.ShortUrlService;
import com.keao.edu.user.service.SysConfigService;
import com.keao.edu.util.collection.MapUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ExamOrganizationRelationServiceImpl extends BaseServiceImpl<Long, ExamOrganizationRelation> implements ExamOrganizationRelationService {
	
	@Autowired
	private ExamOrganizationRelationDao examOrganizationRelationDao;
	@Autowired
	private ExaminationBasicDao examinationBasicDao;
	@Autowired
	private OrganizationService organizationService;
	@Autowired
	private ShortUrlService shortUrlService;
	@Autowired
	private SysUserFeignService sysUserFeignService;
	@Autowired
	private SysMessageFeignService sysMessageFeignService;
	@Autowired
	private SysConfigService sysConfigService;

	@Override
	public BaseDAO<Long, ExamOrganizationRelation> getDAO() {
		return examOrganizationRelationDao;
	}

	@Override
	public PageInfo<ExamOrganizationRelation> queryExamOrgans(ExamOrganizationRelationQueryInfo queryInfo) {
		PageInfo<ExamOrganizationRelation> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<String, Object>();
		MapUtil.populateMap(params, queryInfo);

		List<Integer> nextLevelOrganIds = organizationService.getChildOrganIds(queryInfo.getOrganId(), true);
		params.put("organIds", nextLevelOrganIds);

		List<ExamOrganizationRelation> dataList = new ArrayList<>();
		int count = this.findCount(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = this.getDAO().queryPage(params);
			List<Integer> organIds = dataList.stream().map(ExamOrganizationRelation::getOrganId).collect(Collectors.toList());
			List<ExamOrganizationRelation> countInfos = examOrganizationRelationDao.countExamOrganStudentAndPayment(queryInfo.getExamId(), organIds);
			Map<Integer, ExamOrganizationRelation> organCountInfoMap = countInfos.stream().collect(Collectors.toMap(ExamOrganizationRelation::getOrganId, e -> e));
			for (ExamOrganizationRelation examOrganizationRelation : dataList) {
				ExamOrganizationRelation countInfo = organCountInfoMap.get(examOrganizationRelation.getOrganId());
				if(Objects.nonNull(countInfo)){
					examOrganizationRelation.setTotalRegistrationStudentNum(countInfo.getTotalRegistrationStudentNum());
					examOrganizationRelation.setTotalPaymentAmount(countInfo.getTotalPaymentAmount());
				}
			}
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
	public void updateExamOrganizationRelation(ExamOrganizationRelation examOrganizationRelation) {
		if(Objects.isNull(examOrganizationRelation.getExaminationBasicId())){
			throw new BizException("请指定考级项目");
		}
		if(Objects.isNull(examOrganizationRelation.getOrganId())){
			throw new BizException("请指定合作单位");
		}
		Organization organization = organizationService.get(examOrganizationRelation.getOrganId());
		if(Objects.isNull(organization)){
			throw new BizException("合作单位不存在");
		}
		examOrganizationRelation.setTenantId(TenantContextHolder.getTenantId().toString());
		if(Objects.isNull(examOrganizationRelation.getSettlementType())){
			examOrganizationRelation.setSettlementType(organization.getSettlementType());
		}
		if(Objects.isNull(organization.getShareProfitAmount())){
			examOrganizationRelation.setShareProfitAmount(organization.getShareProfitAmount());
		}
		examOrganizationRelation.setTotalRegistrationStudentNum(BigDecimal.ZERO.intValue());
		examOrganizationRelation.setTotalPaymentAmount(BigDecimal.ZERO);
		Set<Integer> organIds = examOrganizationRelationDao.getOrganIdsWithExam(examOrganizationRelation.getExaminationBasicId());
		if(organIds.contains(examOrganizationRelation.getOrganId())){
			examOrganizationRelationDao.update(examOrganizationRelation);
		}else{
			examOrganizationRelationDao.insert(examOrganizationRelation);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void sendUrl(Integer examId, String organIdStrs) {
		if(Objects.isNull(examId)){
			throw new BizException("请指定考级项目");
		}
		if(StringUtils.isBlank(organIdStrs)){
			throw new BizException("请指定合作单位");
		}
		List<ExamOrganizationRelation> examOrgans = examOrganizationRelationDao.getWithExam(examId);
		Set<Integer> existOrganizationIds = examOrgans.stream().map(ExamOrganizationRelation::getOrganId).collect(Collectors.toSet());
		List<Integer> organIds = Arrays.asList(organIdStrs.split(",")).stream().map(e -> Integer.valueOf(e)).collect(Collectors.toList());
		for (Integer organId : organIds) {
			if(!existOrganizationIds.contains(organId)){
				throw new BizException("存在未关联到考级项目的合作单位");
			}
		}

		ExaminationBasic examinationBasic = examinationBasicDao.get(examId.longValue());
		if(Objects.isNull(examinationBasic)){
			throw new BizException("考级项目不存在");
		}

		SysConfig baseUrlConfig = sysConfigService.findByParamName(SysConfigService.BASE_API_URL);
		String baseUrl="";
		if(Objects.nonNull(baseUrlConfig)){
			baseUrl=baseUrlConfig.getParanValue();
		}
		baseUrl = baseUrl+"/#/signUp?";

		for (ExamOrganizationRelation examOrgan : examOrgans) {
			if(YesOrNoEnum.YES.equals(examOrgan.getSendUrlFlag())){
				continue;
			}
			String registrationUrl = baseUrl + "examId=" + examOrgan.getExaminationBasicId();
			String registShortUrl = shortUrlService.createShortUrl(registrationUrl);

			examOrgan.setUrl(registShortUrl);
			examOrgan.setSendUrlFlag(YesOrNoEnum.YES);

			SysUser student = sysUserFeignService.queryUserById(examOrgan.getOrganId());
			Map<Integer, String> userPhoneMap = new HashMap<>();
			userPhoneMap.put(examOrgan.getOrganId(), student.getPhone());

			SysMessageParams sysMessageParams=new SysMessageParams(MessageSenderPluginContext.MessageSender.YIMEI, MessageTypeEnum.EXAM_REGISTRATION_URL_PUSH,
					userPhoneMap, null, 0, null, null, registShortUrl);
			sysMessageFeignService.batchSendMessage(sysMessageParams);
		}

		examOrganizationRelationDao.batchUpdate(examOrgans);

		if(examinationBasic.getStatus().equals(ExamStatusEnum.SETTING)){
			examinationBasic.setStatus(ExamStatusEnum.NOT_START);
			examinationBasicDao.update(examinationBasic);
		}
	}

	@Override
	public PageInfo<Organization> queryUnRelatedOrgans(ExamOrganizationRelationQueryInfo queryInfo) {
		PageInfo<Organization> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<String, Object>();
		MapUtil.populateMap(params, queryInfo);

		List<Integer> nextLevelOrganIds = organizationService.getChildOrganIds(queryInfo.getOrganId(), true);
		params.put("organIds", nextLevelOrganIds);

		List<Organization> dataList = new ArrayList<>();
		int count = examOrganizationRelationDao.countUnRelatedOrgans(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = examOrganizationRelationDao.queryUnRelatedOrgans(params);
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}
}
