package com.uas.platform.b2b.mobile.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import com.uas.platform.b2b.dao.UserBaseInfoDao;
import com.uas.platform.b2b.dao.UserDao;
import com.uas.platform.b2b.dao.UserPositionDao;
import com.uas.platform.b2b.mobile.dao.AppFlowOperationDao;
import com.uas.platform.b2b.mobile.dao.ApprovalLogDao;
import com.uas.platform.b2b.mobile.dao.FeePleaseDao;
import com.uas.platform.b2b.mobile.dao.MobileAuditLogDao;
import com.uas.platform.b2b.mobile.dao.SignAppDao;
import com.uas.platform.b2b.mobile.dao.SignCardDao;
import com.uas.platform.b2b.mobile.dao.VacationDao;
import com.uas.platform.b2b.mobile.dao.WorkDailyDao;
import com.uas.platform.b2b.mobile.dao.WorkOvertimeDao;
import com.uas.platform.b2b.mobile.enumeration.MobileStatus;
import com.uas.platform.b2b.mobile.model.AppFlowOperation;
import com.uas.platform.b2b.mobile.model.ApprovalLog;
import com.uas.platform.b2b.mobile.model.FeePlease;
import com.uas.platform.b2b.mobile.model.MobileAuditLog;
import com.uas.platform.b2b.mobile.model.SignApp;
import com.uas.platform.b2b.mobile.model.SignCard;
import com.uas.platform.b2b.mobile.model.Vacation;
import com.uas.platform.b2b.mobile.model.WorkDaily;
import com.uas.platform.b2b.mobile.model.WorkOvertime;
import com.uas.platform.b2b.mobile.service.MobileFlowService;
import com.uas.platform.b2b.model.FlowNode;
import com.uas.platform.b2b.model.User;
import com.uas.platform.b2b.model.UserPosition;
import com.uas.platform.b2b.service.ApprovalFlowService;
import com.uas.platform.b2b.temporary.model.AuditInfoDone;
import com.uas.platform.b2b.temporary.model.AuditInfoTodo;
import com.uas.platform.b2b.temporary.model.MobileDocumentsProcess;
import com.uas.platform.b2b.temporary.model.MobileNodes;
import com.uas.platform.b2b.temporary.model.UserInfo;
import com.uas.platform.core.model.PageInfo;
import com.uas.platform.core.model.PageParams;

@Service
public class MobileFlowServiceImpl implements MobileFlowService {

	@Autowired
	private ApprovalLogDao approvalLogDao;

	@Autowired
	private AppFlowOperationDao appFlowOperationDao;

	@Autowired
	private MobileAuditLogDao mobileAuditLogDao;

	@Autowired
	private ApprovalFlowService approvalFlowService;

	@Autowired
	private VacationDao vacationDao;

	@Autowired
	private WorkDailyDao workDailyDao;

	@Autowired
	private FeePleaseDao feePleaseDao;

	@Autowired
	private WorkOvertimeDao workOvertimeDao;

	@Autowired
	private UserBaseInfoDao userBaseInfoDao;

	@Autowired
	private UserDao userDao;

	@Autowired
	private UserPositionDao userPositionDao;

	@Autowired
	private SignAppDao signAppDao;

	@Autowired
	private SignCardDao signCardDao;

	@Override
	public ModelMap getAuditTodo(Integer count, Integer page, Long enuu, Long emuu) {
		ModelMap map = new ModelMap();
		PageParams params = new PageParams();
		params.setCount(count);
		params.setPage(page);
		final PageInfo pageInfo = new PageInfo(params);
		pageInfo.filter("nodedealuu", emuu);
		pageInfo.filter("enuu", enuu);
		pageInfo.filter("statuscode", MobileStatus.UNAUDIT.name());
		Page<AppFlowOperation> operations = appFlowOperationDao.findAll(new Specification<AppFlowOperation>() {
			@Override
			public Predicate toPredicate(Root<AppFlowOperation> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
		List<AuditInfoTodo> autodos = new ArrayList<AuditInfoTodo>();
		if (!CollectionUtils.isEmpty(operations.getContent())) {
			for (AppFlowOperation op : operations.getContent()) {
				AuditInfoTodo todo = new AuditInfoTodo();
				todo.setJp_id(op.getId());
				todo.setJp_codevalue(op.getSourceid());
				todo.setJp_launcherid(op.getDealuu());
				todo.setJp_launchername(userBaseInfoDao.findByUserUU(op.getDealuu()).getUserName());
				todo.setJp_launchtime(op.getRecorddate());
				todo.setJp_name(op.getCaller());
				todo.setJp_nodedealman(op.getNodedealuu());
				todo.setJp_nodeid(op.getKeyvalue());
				todo.setJp_nodename(op.getNodename());
				todo.setJp_status(op.getStatus());
				autodos.add(todo);
				Collections.sort(autodos);
			}
		}
		map.put("data", autodos);
		map.put("success", true);
		map.put("totalCount", operations.getTotalElements());
		return map;
	}

	@Override
	public ModelMap getAuditDone(Integer count, Integer page, Long enuu, Long emuu) {
		ModelMap map = new ModelMap();
		PageParams params = new PageParams();
		params.setCount(count);
		params.setPage(page);
		final PageInfo pageInfo = new PageInfo(params);
		pageInfo.filter("nodedealuu", emuu);
		pageInfo.filter("enuu", enuu);
		pageInfo.filter("statuscode", MobileStatus.AUDITED.name());
		Page<AppFlowOperation> operations = appFlowOperationDao.findAll(new Specification<AppFlowOperation>() {
			@Override
			public Predicate toPredicate(Root<AppFlowOperation> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
		List<AuditInfoDone> dones = new ArrayList<AuditInfoDone>();
		if (!CollectionUtils.isEmpty(operations.getContent())) {
			for (AppFlowOperation log : operations.getContent()) {
				AuditInfoDone done = new AuditInfoDone();
				done.setJn_dealmanid(log.getNodedealuu());
				done.setJn_dealmanname(log.getNodedealname());
				done.setJn_dealresult(log.getResult());
				done.setJn_dealtime(log.getDealtime());
				done.setJn_name(log.getCaller());
				done.setJn_operateddescription(log.getDescription());
				done.setJp_keyvalue(log.getKeyvalue());
				done.setJp_launcherid(log.getDealuu());
				done.setJp_launchername(userBaseInfoDao.findByUserUU(log.getDealuu()).getUserName());
				done.setJp_name(log.getNodename());
				done.setJp_nodeid(log.getSourceid());
				dones.add(done);
				Collections.sort(dones);
			}
		}
		map.put("data", dones);
		map.put("success", true);
		map.put("totalCount", operations.getTotalElements());
		return map;
	}

	@Override
	public ModelMap getNodesAndLog(Long id, String caller) {
		ModelMap map = new ModelMap();
		List<ApprovalLog> logs = approvalLogDao.getByKeyvalueAndCaller(id, caller);
		List<MobileNodes> mbds = new ArrayList<MobileNodes>();
		List<MobileDocumentsProcess> mdps = new ArrayList<MobileDocumentsProcess>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		if (!CollectionUtils.isEmpty(logs)) {
			for (ApprovalLog log : logs) {
				MobileNodes mbd = new MobileNodes();
				mbd.setJp_caller(log.getCaller());
				mbd.setJp_id(log.getId());
				mbd.setJp_nodedealman(log.getNodedealman());
				mbd.setJp_nodedealmanname(log.getNodedealmanname());
				mbd.setJp_processdefid(log.getNodename());
				mbd.setJp_nodename(log.getNodename());
				mbd.setJp_keyvalue(log.getKeyvalue());
				mbds.add(mbd);
				Collections.sort(mbds);
			}
			List<AppFlowOperation> operations = appFlowOperationDao.findBySourceidAndCaller(id, caller);
			if (!CollectionUtils.isEmpty(operations)) {
				for (AppFlowOperation op : operations) {
					if (!op.getStatuscode().equals(MobileStatus.UNAUDIT.name())) {// 只查询已审核过的
						MobileDocumentsProcess mdp = new MobileDocumentsProcess();
						mdp.setJn_dealmanid(op.getNodedealuu());
						mdp.setJn_dealmanname(op.getNodedealname());
						mdp.setJn_dealTime(sdf.format(op.getDealtime()));
						mdp.setJn_id(op.getId());
						mdp.setJn_name(op.getNodename());
						mdp.setJn_nodeDescription(op.getDescription());
						mdp.setJn_result(op.getResult());
						mdps.add(mdp);
						Collections.sort(mdps);
					}
				}
			}
			map.put("nodes", mdps);
			map.put("data", mbds);
			map.put("success", true);
		} else {
			map.put("success", false);
		}
		return map;
	}

	@Override
	public ModelMap auditDocuments(Long id, String description, Integer dealtype) {
		ModelMap map = new ModelMap();
		AppFlowOperation op = appFlowOperationDao.findOne(id);
		if (op == null) {
			map.put("error", "单据不存在，可能已被删除！");
		} else {
			if (op.getResult() == null || !op.getResult().equals(MobileStatus.AUDITED.getPhrase())) {
				op.setStatus(MobileStatus.AUDITED.getPhrase());
				op.setStatuscode(MobileStatus.AUDITED.name());
				op.setDescription(description);
				op.setDealtime(new Date());
				ApprovalLog applog = approvalLogDao.findOne(op.getKeyvalue());
				applog.setStatus(MobileStatus.AUDITED.getPhrase());
				applog.setStatuscode(MobileStatus.AUDITED.name());
				if (dealtype.equals(MobileStatus.AGREED.getValue())) {
					op.setResult(MobileStatus.AGREED.getPhrase());
				}
				if (dealtype.equals(MobileStatus.NOTAGREED.getValue())) {
					op.setResult(MobileStatus.NOTAGREED.getPhrase());
				}
				op = appFlowOperationDao.save(op);

				// 生成日志记录
				MobileAuditLog log = new MobileAuditLog();
				log.setDealname(op.getNodedealname());
				log.setDealresult(op.getResult());
				log.setDealtime(log.getDealtime());
				log.setDealuu(op.getNodedealuu());
				log.setInstanceid(op.getId());
				log.setEnuu(op.getEnuu());
				mobileAuditLogDao.save(log);

				// 如果后面有其他节点，继续生成单据，通向下一个，并且记录审核记录(已通过才继续)
				if (op.getResult().equals(MobileStatus.AGREED.getPhrase())) {
					Integer maxNode = approvalFlowService.getMaxNodeByEnuuAndAppName(op.getEnuu(), op.getCaller());
					if (maxNode != null) {
						if (op.getNodelevel() < maxNode) {
							FlowNode node = approvalFlowService.getNodeInfoByEnuuAndAppNameAndNodelev(op.getEnuu(),
									op.getCaller(), op.getNodelevel() + 1);
							AppFlowOperation oper = new AppFlowOperation();
							oper.setCaller(op.getCaller());
							oper.setDealname(op.getDealname());
							oper.setDealuu(op.getDealuu());
							oper.setEnuu(op.getEnuu());
							oper.setKeyvalue(op.getKeyvalue());
							oper.setNodedealname(node.getEmname());
							oper.setNodedealuu(node.getEmcode());
							oper.setNodelevel(node.getNodelev());
							oper.setNodename(node.getNodename());
							oper.setProcessnote(
									"[" + op.getNodedealname() + "]" + op.getResult() + " 备注：" + op.getDescription());
							oper.setRecorddate(op.getRecorddate());
							oper.setSourceid(op.getSourceid());
							oper.setStatus(MobileStatus.UNAUDIT.getPhrase());
							oper.setStatuscode(MobileStatus.UNAUDIT.name());
							oper = appFlowOperationDao.save(oper);
							if (oper.getId() != null) {
								map.put("success", true);
							} else {
								map.put("success", false);
							}
						}
						if (Objects.equals(op.getNodelevel(), maxNode)) { // 如果为最后一个，原单据状态变为已审批
							if (op.getCaller().equals(MobileStatus.VACATION.getPhrase())) {// 请假单
								Vacation va = vacationDao.findOne(op.getSourceid());
								va.setVa_statuscode(MobileStatus.AUDITED.name());
								va.setVa_status(MobileStatus.AUDITED.getPhrase());
								vacationDao.save(va);
								map.put("success", true);
							}
							if (op.getCaller().equals(MobileStatus.WORKDAILY.getPhrase())) {// 工作日报
								WorkDaily wo = workDailyDao.findOne(op.getSourceid());
								wo.setWd_statuscode(MobileStatus.AUDITED.name());
								wo.setWd_status(MobileStatus.AUDITED.getPhrase());
								workDailyDao.save(wo);
								map.put("success", true);
							}
							if (op.getCaller().equals(MobileStatus.WORKOVERTIME.getPhrase())) {// 加班申请
								WorkOvertime wot = workOvertimeDao.findOne(op.getSourceid());
								wot.setWo_statuscode(MobileStatus.AUDITED.name());
								wot.setWo_status(MobileStatus.AUDITED.getPhrase());
								workOvertimeDao.save(wot);
								map.put("success", true);
							}
							if (op.getCaller().equals(MobileStatus.FEEPLEASE.getPhrase())) {// 出差单
								FeePlease fee = feePleaseDao.findOne(op.getSourceid());
								fee.setFp_statuscode(MobileStatus.AUDITED.name());
								fee.setFp_status(MobileStatus.AUDITED.getPhrase());
								feePleaseDao.save(fee);
								map.put("success", true);
							}
							if (op.getCaller().equals(MobileStatus.SIGNAPP.getPhrase())) {// 申诉单
								SignApp app = signAppDao.findOne(op.getSourceid());
								app.setStatus(MobileStatus.AUDITED.getPhrase());
								app.setStatuscode(MobileStatus.AUDITED.name());
								signAppDao.save(app);

								// 插入数据到打卡记录中
								SignCard card = new SignCard();
								card.setCl_address(app.getAddress());
								card.setCl_date(app.getSigntime());
								card.setCl_emname(app.getEmname());
								card.setCl_phone(app.getMobile());
								card.setEmcode(app.getEmuu());
								card.setEnuu(app.getUu());
								card = signCardDao.save(card);
								if (card.getId() != null) {
									map.put("success", true);
								} else {
									map.put("success", false);
								}
							}
						}
					}
				}
			} else if (op.getResult().equals(MobileStatus.AUDITED.getPhrase())) {
				map.put("error", "单据已被审核");
			}
		}
		return map;
	}

	@Override
	public ModelMap getUsersInfo(Long enuu) {
		ModelMap map = new ModelMap();
		List<User> users = userDao.findByEnUU(enuu);
		List<UserInfo> infos = new ArrayList<UserInfo>();
		if (!CollectionUtils.isEmpty(users)) {
			for (User user : users) {
				UserInfo info = new UserInfo();
				info.setEmcode(user.getUserUU());
				info.setEmemail(user.getUserEmail());
				info.setEmimid(user.getUserIMId());
				info.setEmphone(user.getUserTel());
				info.setEmname(user.getUserName());
				info.setEmsex(user.getUserSex());
				UserPosition pos = userPositionDao.getUserByUseruuAndEnuu(user.getUserUU(), enuu);
				if (pos != null) {
					info.setEmdepart(pos.getDepartment());
					info.setEmrole(pos.getRole());
				}
				infos.add(info);
			}
		}
		map.put("data", infos);
		return map;
	}

}
