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.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 org.springframework.util.CollectionUtils;

import com.uas.platform.b2b.dao.UserBaseInfoDao;
import com.uas.platform.b2b.mobile.dao.AppFlowOperationDao;
import com.uas.platform.b2b.mobile.dao.ApprovalLogDao;
import com.uas.platform.b2b.mobile.dao.WorkOvertimeDao;
import com.uas.platform.b2b.mobile.dao.WorkOvertimeDetDao;
import com.uas.platform.b2b.mobile.enumeration.MobileStatus;
import com.uas.platform.b2b.mobile.model.AppFlowOperation;
import com.uas.platform.b2b.mobile.model.AppLog;
import com.uas.platform.b2b.mobile.model.ApprovalLog;
import com.uas.platform.b2b.mobile.model.WorkOvertime;
import com.uas.platform.b2b.mobile.model.WorkOvertimeDet;
import com.uas.platform.b2b.mobile.service.WorkOvertimeService;
import com.uas.platform.b2b.model.FlowNode;
import com.uas.platform.b2b.service.ApprovalFlowService;
import com.uas.platform.core.model.PageInfo;
import com.uas.platform.core.model.PageParams;

@Service
public class WorkOvertimeServiceImpl implements WorkOvertimeService {

	@Autowired
	private WorkOvertimeDetDao workOvertimeDetDao;

	@Autowired
	private WorkOvertimeDao workOvertimeDao;

	@Autowired
	private ApprovalFlowService approvalFlowService;

	@Autowired
	private ApprovalLogDao approvalLogDao;

	@Autowired
	private AppFlowOperationDao appFlowOperationDao;

	@Autowired
	private UserBaseInfoDao userBaseInfoDao;


	@Override
	public ModelMap saveWorkOvertime(WorkOvertime workOvertime, List<WorkOvertimeDet> workOvertimeDets) {
		ModelMap map = new ModelMap();
		Long id = 0L;
		if (workOvertime.getWo_id() == null) {// 新增单据
			SimpleDateFormat sdf = new SimpleDateFormat("yyMMmmSS");
			workOvertime.setWo_code("WO" + sdf.format(new Date()));
			workOvertime.setWo_status(MobileStatus.ENTERING.getPhrase());
			workOvertime.setWo_statuscode(MobileStatus.ENTERING.name());
			workOvertime.setWo_recorder(userBaseInfoDao.findByUserUU(workOvertime.getEmcode()).getUserName());
			workOvertime.setWo_date(new Date());
			workOvertime.setOrderdate(new Date());
			Set<WorkOvertimeDet> workOvertimeDetails = new HashSet<WorkOvertimeDet>();
			if (!CollectionUtils.isEmpty(workOvertimeDets)) {
				for (WorkOvertimeDet workOvertimeDet : workOvertimeDets) {
					workOvertimeDet.setEmcode(workOvertime.getEmcode());
					workOvertimeDet
							.setWod_empname(userBaseInfoDao.findByUserUU(workOvertime.getEmcode()).getUserName());
					workOvertimeDet.setWorkOvertime(workOvertime);
					workOvertimeDetails.add(workOvertimeDet);
				}
			}
			workOvertimeDets = workOvertimeDetDao.save(workOvertimeDetails);
			if (!CollectionUtils.isEmpty(workOvertimeDets)) {
				map.put("success", true);
				id = workOvertimeDets.get(0).getWorkOvertime().getWo_id();
				map.put("wo_id", id);
			} else {
				map.put("success", false);
			}
		} else {// 更新单据
			WorkOvertime wo = workOvertimeDao.findOne(workOvertime.getWo_id());
			id = workOvertime.getWo_id();
			if (wo != null) {
				wo.setWo_status(MobileStatus.ENTERING.getPhrase());
				wo.setWo_statuscode(MobileStatus.ENTERING.name());
				wo.setWo_worktask(workOvertime.getWo_worktask());
				wo.setWo_date(new Date());
				wo.setOrderdate(new Date());
				wo.setWo_recorder(userBaseInfoDao.findByUserUU(workOvertime.getEmcode()).getUserName());
				workOvertimeDao.save(wo);// 更新主表
				if (!CollectionUtils.isEmpty(workOvertimeDets)) {
					for (WorkOvertimeDet det : workOvertimeDets) {
						if (det.getWod_id() != null) {
							WorkOvertimeDet wodet = workOvertimeDetDao.findOne(det.getWod_id());
							wodet.setWod_count(det.getWod_count());
							wodet.setWod_enddate(det.getWod_enddate());
							wodet.setWod_startdate(det.getWod_startdate());
							workOvertimeDetDao.save(wodet);
						}
					}
				}
				map.put("wo_id", id);
				map.put("success", true);
			}
		}
		// 审批流
		// TODO 暂时这里先只做人员的线路
		String appName = MobileStatus.WORKOVERTIME.getPhrase();
		FlowNode node = approvalFlowService.getNodeInfoByEnuuAndEmcodeAndAppName(workOvertime.getEnuu(),
				workOvertime.getEmcode(), appName);
		Integer nodelevel = -1;
		if (node != null) {
			nodelevel = node.getNodelev();
		}
		Integer maxNode = approvalFlowService.getMaxNodeByEnuuAndAppName(workOvertime.getEnuu(), appName);
		if (maxNode != null) {
			if (nodelevel < maxNode) {
				AppLog log = new AppLog();
				log.setStatus(MobileStatus.ENTERING.getPhrase());
				log.setStatusCode(MobileStatus.ENTERING.name());
				log.setSourceid(id);
				log.setSourcedate(new Date());
				log.setKeyvalue(id);
				log.setCaller(appName);
				log.setEmcode(workOvertime.getEmcode());
				log.setEnuu(workOvertime.getEnuu());
				for (int i = nodelevel + 1; i <= maxNode; i++) {
					ApprovalLog applog = new ApprovalLog(log);
					applog.setNodedealman(approvalFlowService
							.getNodeInfoByEnuuAndAppNameAndNodelev(workOvertime.getEnuu(), appName, i).getEmcode());
					applog.setNodename(approvalFlowService
							.getNodeInfoByEnuuAndAppNameAndNodelev(workOvertime.getEnuu(), appName, i).getNodename());
					applog.setProcessid(approvalFlowService
							.getNodeInfoByEnuuAndAppNameAndNodelev(workOvertime.getEnuu(), appName, i).getId());
					applog = approvalLogDao.save(applog);
					node = approvalFlowService.getNodeInfoByEnuuAndAppNameAndNodelev(workOvertime.getEnuu(), appName,
							nodelevel + 1);
					if (applog.getId() != null) {
						if (applog.getNodedealman().equals(approvalFlowService
								.getNodeInfoByEnuuAndAppNameAndNodelev(workOvertime.getEnuu(), appName, nodelevel + 1)
								.getEmcode())) {
							// 新增待审批
							AppFlowOperation operation = new AppFlowOperation();
							operation.setCaller(appName);
							operation.setCaller(appName);
							operation.setDealname(workOvertime.getWo_recorder());
							operation.setDealuu(workOvertime.getEmcode());
							operation.setKeyvalue(applog.getId());
							operation.setNodedealname(node.getEmname());
							operation.setRecorddate(new Date());
							operation.setStatus(MobileStatus.UNAUDIT.getPhrase());
							operation.setStatuscode(MobileStatus.UNAUDIT.name());
							operation.setEnuu(workOvertime.getEnuu());
							operation.setNodedealuu(node.getEmcode());
							operation.setNodelevel(node.getNodelev());
							operation.setSourceid(workOvertime.getWo_id());
							operation = appFlowOperationDao.save(operation);
							if (operation.getId() != null) {
								if (id != null) {// 更新单据状态
									workOvertime = workOvertimeDao.findOne(id);
									workOvertime.setWo_status(MobileStatus.COMMITED.getPhrase());
									workOvertime.setWo_statuscode(MobileStatus.COMMITED.name());
									workOvertimeDao.save(workOvertime);
								}
								map.put("success", true);
							} else {
								map.put("success", false);
							}
						}

					}
				}
			}
			if (Objects.equals(nodelevel, maxNode)) {
				workOvertime = workOvertimeDao.findOne(id);
				workOvertime.setWo_status(MobileStatus.AUDITED.getPhrase());
				workOvertime.setWo_statuscode(MobileStatus.AUDITED.name());
				workOvertimeDao.save(workOvertime);
			}
		}
		return map;
	}

	@Override
	public ModelMap getWorkOvertime(Long enuu, Long emcode, Integer pageNumber, Integer pageSize) {
		ModelMap map = new ModelMap();
		PageParams params = new PageParams();
		params.setCount(pageSize);
		params.setPage(pageNumber);
		String sorting = "{\"orderdate\":\"desc\"}";
		params.setSorting(sorting);
		final PageInfo pageInfo = new PageInfo(params);
		pageInfo.filter("emcode", emcode);
		pageInfo.filter("enuu", enuu);
		Page<WorkOvertime> workOvertime = workOvertimeDao.findAll(new Specification<WorkOvertime>() {
			@Override
            public Predicate toPredicate(Root<WorkOvertime> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
				return query.where(pageInfo.getPredicates(root, query, builder)).getRestriction();
			}
		}, pageInfo);
		map.put("listdata", workOvertime.getContent());
		return map;
	}
}
