package com.goafanti.contract.service.impl;

import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.dao.*;
import com.goafanti.common.enums.ContractStatus;
import com.goafanti.common.enums.DeleteStatus;
import com.goafanti.common.enums.NoticeReadStatus;
import com.goafanti.common.enums.NoticeStatus;
import com.goafanti.common.model.Contract;
import com.goafanti.common.model.ContractLog;
import com.goafanti.common.model.Notice;
import com.goafanti.common.model.User;
import com.goafanti.common.utils.AsyncUtils;
import com.goafanti.common.utils.DateUtils;
import com.goafanti.common.utils.StringUtils;
import com.goafanti.contract.bo.ContractClientListBo;
import com.goafanti.contract.bo.ContractDetail;
import com.goafanti.contract.bo.ContractManageListBo;
import com.goafanti.contract.bo.ContractSerialNumber;
import com.goafanti.contract.service.ContractService;
import com.goafanti.core.mybatis.BaseMybatisDao;
import com.goafanti.core.mybatis.page.Pagination;
import com.goafanti.core.shiro.token.TokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;

@Service
public class ContractServiceImpl extends BaseMybatisDao<ContractMapper> implements ContractService {
	@Autowired
	private ContractMapper		contractMapper;
	@Autowired
	private ContractLogMapper	contractLogMapper;
	@Autowired
	private UserMapper			userMapper;
	@Autowired
	private AsyncUtils		asyncUtils;
	@Autowired
	private PatentInfoMapper	patentInfoMapper;
	@Autowired
	private CopyrightInfoMapper	copyrightInfoMapper;
	@Autowired
	private OrgCognizanceMapper	orgCognizanceMapper;
	@Autowired
	private TechProjectMapper	techProjectMapper;

	@SuppressWarnings("unchecked")
	@Override
	public Pagination<ContractManageListBo> getManageList(String contractId, Integer serialNumber, Integer type,
			Integer status, String startDateFormattedDate, String endDateFormattedDate, Integer province,
			String unitName, String uid, Integer pNo, Integer pSize) {
		Map<String, Object> params = disposeParams(contractId, serialNumber, type, status, startDateFormattedDate,
				endDateFormattedDate, province, unitName, uid);

		if (!TokenManager.hasRole(AFTConstants.SUPERADMIN)) {
			params.put("principal", TokenManager.getAdminId());
		}

		if (pNo == null || pNo < 0) {
			pNo = 1;
		}

		if (pSize == null || pSize < 0 || pSize > 10) {
			pSize = 10;
		}

		return (Pagination<ContractManageListBo>) findPage("findManageContractListByPage", "findManageContractCount",
				params, pNo, pSize);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Pagination<ContractClientListBo> getClientList(String contractId, Integer serialNumber, Integer type,
			Integer status, String startDateFormattedDate, String endDateFormattedDate, String completeStartDate,
			String completeEndDate, Integer pNo, Integer pSize) {

		Map<String, Object> params = disposeParams(contractId, serialNumber, type, status, startDateFormattedDate,
				endDateFormattedDate, null, null, TokenManager.getUserId());

		Date lStart = null;
		Date lEnd = null;
		if (!StringUtils.isBlank(completeStartDate)) {
			try {
				lStart = DateUtils.parseDate(completeStartDate, AFTConstants.YYYYMMDD);
			} catch (ParseException e) {
			}
		}

		if (null != lStart) {
			params.put("lStart", lStart);
		}

		if (!StringUtils.isBlank(completeEndDate)) {
			try {
				lEnd = DateUtils.addDays(DateUtils.parseDate(completeEndDate, AFTConstants.YYYYMMDD), 1);
			} catch (ParseException e) {
			}
		}

		if (null != lEnd) {
			params.put("lEnd", lEnd);
		}

		if (pNo == null || pNo < 0) {
			pNo = 1;
		}

		if (pSize == null || pSize < 0) {
			pSize = 10;
		}

		return (Pagination<ContractClientListBo>) findPage("findClientContractListByPage", "findClientContractCount",
				params, pNo, pSize);
	}

	@Override
	public Contract saveManageContract(Contract c) {
		c.setStatus(ContractStatus.CREATE.getCode());
		c = disposeContract(c);
		contractMapper.insert(c);
		contractLogMapper.insert(disposeContractLog(c));
		return c;
	}

	@Override
	public int updateContractByManage(Contract contract) {
		return contractMapper.updateByPrimaryKeySelective(contract);
	}

	@Override
	public void insertManageSubmit(Contract c, String[] principals, String signDateFormattedDate) {
		Date signDate = null;
		if (!StringUtils.isBlank(signDateFormattedDate)) {
			try {
				signDate = DateUtils.parseDate(signDateFormattedDate, AFTConstants.YYYYMMDDHHMMSS);
			} catch (ParseException e) {
			}
		}
		c.setStatus(ContractStatus.SIGN.getCode());
		c.setSignDate(signDate);
		c = disposeContract(c);
		contractMapper.insert(c);
		ContractLog clog = disposeContractLog(c);
		clog.setStatus(ContractStatus.SIGN.getCode());
		clog.setRecordTime(signDate);

		/*
		 * ContractLog log = new ContractLog(); log.setCid(c.getId());
		 * log.setComment(c.getComment()); log.set
		 */

		List<ContractLog> logs = new ArrayList<>();
		List<Notice> notice = new ArrayList<>();
		logs.add(clog);

		for (int i = 0; i < principals.length; i++) {
			ContractLog log = disposeContractLog(c);
			log.setPrincipal(principals[i]);
			log.setStatus(ContractStatus.CIRCULATION.getCode());
			logs.add(log);
			notice.add(createNotice(c, log));
		}
		contractLogMapper.insertBatch(logs);
		asyncUtils.addNoticeBatch(notice);

	}

	@Override
	public ContractDetail selectContractDetail(String id) {
		return contractMapper.selectContractDetail(id);
	}

	@Override
	public Contract selectByPrimaryKey(String id) {
		return contractMapper.selectByPrimaryKey(id);
	}

	@Override
	public int updateByPrimaryKeySelective(Contract contract) {
		return contractMapper.updateByPrimaryKeySelective(contract);
	}

	// update to 18
	@Override
	public void updateSubmit(Contract c, String[] principals, String signDateFormattedDate) {
		Date signDate = null;
		if (!StringUtils.isBlank(signDateFormattedDate)) {
			try {
				signDate = DateUtils.parseDate(signDateFormattedDate, AFTConstants.YYYYMMDDHHMMSS);
			} catch (ParseException e) {
			}
		}

		c.setStatus(ContractStatus.SIGN.getCode());

		c.setSignDate(signDate);
		contractMapper.updateByPrimaryKeySelective(c);
		
		ContractLog l = new ContractLog();
		l.setId(UUID.randomUUID().toString());
		l.setCid(c.getId());
		//l.setComment(c.getComment());
		l.setOperator(TokenManager.getAdminId());
		l.setPrincipal(TokenManager.getAdminId());
		l.setRecordTime(signDate);
		l.setStatus(ContractStatus.SIGN.getCode());
		

		List<ContractLog> logs = new ArrayList<>();
		List<Notice> notice = new ArrayList<>();
		
		logs.add(l);
		
		for (int i = 0; i < principals.length; i++) {
			ContractLog log = disposeContractLog(c);
			log.setStatus(ContractStatus.CIRCULATION.getCode());
			log.setPrincipal(principals[i]);
			log.setOperator(TokenManager.getAdminId());
			logs.add(log);
			notice.add(createNotice(c, log));
		}
		contractLogMapper.insertBatch(logs);
		asyncUtils.addNoticeBatch(notice);
	}

	@Override
	public List<ContractSerialNumber> selectContractSerialNumber() {
		String principal = null;
		if (!TokenManager.hasRole(AFTConstants.SUPERADMIN)) {
			principal = TokenManager.getAdminId();
		}
		return contractMapper.selectContractSerialNumber(principal);
	}

	@Override
	public int deleteByPrimaryKey(List<String> id) {
		patentInfoMapper.batchDeleteByContractId(id);
		copyrightInfoMapper.batchDeleteByContractId(id);
		orgCognizanceMapper.batchDeleteByContractId(id);
		techProjectMapper.batchDeleteByContractId(id);
		return contractMapper.batchDeleteByPrimaryKey(id);
	}

	@Override
	public Contract saveContract(Contract c) {
		c.setStatus(ContractStatus.CREATE.getCode());
		c.setUid(TokenManager.getUserId());
		c = disposeContract(c);
		contractMapper.insert(c);
		contractLogMapper.insert(disposeContractLog(c));
		return c;
	}

	//to update 18
	private ContractLog disposeContractLog(Contract c) {
		ContractLog cl = new ContractLog();
		cl.setId(UUID.randomUUID().toString());
		/*cl.setComment(c.getComment());
		if (TokenManager.getToken() instanceof Admin) {
			cl.setOperator(c.getFounder());
			cl.setPrincipal(c.getFounder());
		}*/
		Calendar now = Calendar.getInstance();
		now.set(Calendar.MILLISECOND, 0);
		cl.setRecordTime(now.getTime());
		cl.setStatus(c.getStatus());
		cl.setCid(c.getId());
		return cl;
	}

	//to update 18
	private Notice createNotice(Contract c, ContractLog l) {
		Contract info = contractMapper.selectByPrimaryKey(c.getId());

		Notice n = new Notice();
		Calendar now = Calendar.getInstance();
		now.set(Calendar.MILLISECOND, 0);
		n.setId(UUID.randomUUID().toString());
		n.setCreateTime(now.getTime());
		n.setReaded(NoticeReadStatus.UNREAD.getCode());

		User u = userMapper.queryById(c.getUid());
		if (null != u) {
			n.setPid(u.getAid());
		}

		n.setUid(c.getUid());
		n.setRid(c.getId());

		n.setAid(l.getPrincipal());
		n.setContent("编号" + info.getSerialNumber() + "  " + ContractStatus.getStatus(c.getStatus()).getDesc());
		n.setNoticeType(NoticeStatus.CONTRACT.getCode());
		/*n.setYear(info.getCognizanceYear());*/
		return n;
	}
	//to update 18
	private Contract disposeContract(Contract c) {
		c.setId(UUID.randomUUID().toString());
		Calendar now = Calendar.getInstance();
		now.set(Calendar.MILLISECOND, 0);
		c.setCreateTime(now.getTime());
		/*if (TokenManager.getToken() instanceof Admin) {
			c.setFounder(TokenManager.getAdminId());
		}

		c.setPatentStatus(ContractBusinessStatus.UNCREATE.getCode());
		c.setCopyrightStatus(ContractBusinessStatus.UNCREATE.getCode());
		c.setTechProjectStatus(ContractBusinessStatus.UNCREATE.getCode());
		c.setCognizanceStatus(ContractBusinessStatus.UNCREATE.getCode());*/
		c.setDeletedSign(DeleteStatus.UNDELETE.getCode());
		return c;
	}

	private Map<String, Object> disposeParams(String contractId, Integer serialNumber, Integer type, Integer status,
			String startDateFormattedDate, String endDateFormattedDate, Integer province, String unitName, String uid) {
		Date cStart = null;
		Date cEnd = null;

		Map<String, Object> params = new HashMap<>();

		if (null != serialNumber) {
			params.put("serialNumber", serialNumber);
		}

		if (null != type) {
			params.put("type", type);
		}

		if (null != status) {
			params.put("status", status);
		}

		if (!StringUtils.isBlank(uid)) {
			params.put("uid", uid);
		}

		if (!StringUtils.isBlank(contractId)) {
			params.put("id", contractId);
		}

		if (!StringUtils.isBlank(startDateFormattedDate)) {
			try {
				cStart = DateUtils.parseDate(startDateFormattedDate, AFTConstants.YYYYMMDD);
			} catch (ParseException e) {
			}
		}

		if (null != cStart) {
			params.put("cStart", cStart);
		}

		if (!StringUtils.isBlank(endDateFormattedDate)) {
			try {
				cEnd = DateUtils.addDays(DateUtils.parseDate(endDateFormattedDate, AFTConstants.YYYYMMDD), 1);
			} catch (ParseException e) {
			}
		}

		if (null != cEnd) {
			params.put("cEnd", cEnd);
		}

		if (null != province) {
			params.put("province", province);
		}

		if (!StringUtils.isBlank(unitName)) {
			params.put("unitName", unitName);
		}
		return params;
	}

	@Override
	public Contract findByUidAndYear(String uid, Integer year) {
		return contractMapper.findByUidAndYear(uid, year);
	}

	@Override
	public Contract findLatelyRecordByUid(String uid) {
		return contractMapper.findLatelyRecordByUid(uid);
	}

}
