package com.jpsoft.shinestar.modules.base.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;
import javax.annotation.Resource;

import cn.hutool.core.date.DateUtil;
import com.jpsoft.shinestar.config.WxConfig;
import com.jpsoft.shinestar.modules.base.entity.*;
import com.jpsoft.shinestar.modules.base.service.*;
import com.jpsoft.shinestar.modules.common.utils.JwtUtil2;
import com.jpsoft.shinestar.modules.common.utils.WechatMessageUtil;
import com.jpsoft.shinestar.modules.workflow.entity.ProcinstActUser;
import com.jpsoft.shinestar.modules.workflow.entity.ProcinstActivity;
import com.jpsoft.shinestar.modules.workflow.service.ProcinstActUserService;
import com.jpsoft.shinestar.modules.workflow.service.ProcinstActivityService;
import com.jpsoft.shinestar.modules.workflow.service.ProcinstService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Minutes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.jpsoft.shinestar.modules.base.dao.WorkOverDAO;
import com.github.pagehelper.Page;
import com.jpsoft.shinestar.modules.common.dto.Sort;
import com.github.pagehelper.PageHelper;

@Slf4j
@Transactional
@Component(value="workOverService")
public class WorkOverServiceImpl implements WorkOverService {
	@Resource(name="workOverDAO")
	private WorkOverDAO workOverDAO;

	@Value("${jwt.secret}")
	private String jwtSecret;

	@Autowired
	private WxConfig wxConfig;

	@Autowired
	private ProcinstService procinstService;

	@Autowired
	private WorkOverPersonService workOverPersonService;

	@Autowired
	private ProcinstActivityService procinstActivityService;

	@Autowired
	private ProcinstActUserService procinstActUserService;

	@Autowired
	private PersonPopedomService personPopedomService;

	@Autowired
	private PersonInfoService personInfoService;

	@Autowired
	private CompanyInfoService companyInfoService;

	@Autowired
	private ApprovalConfigService approvalConfigService;

	@Autowired
	private WorkOverService workOverService;

	@Autowired
	private WorkPersonSchedulingService workPersonSchedulingService;

	@Autowired
	private WorkShiftInfoService workShiftInfoService;

	@Override
	public WorkOver get(String id) {
		// TODO Auto-generated method stub
		return workOverDAO.get(id);
	}

	@Override
	public int insert(WorkOver model) {
		// TODO Auto-generated method stub
		//model.setId(UUID.randomUUID().toString());

		return workOverDAO.insert(model);
	}

	@Override
	public int update(WorkOver model) {
		// TODO Auto-generated method stub
		return workOverDAO.update(model);
	}

	@Override
	public int delete(String id) {
		// TODO Auto-generated method stub
		return workOverDAO.delete(id);
	}

	@Override
	public boolean exist(String id) {
		// TODO Auto-generated method stub
		int count = workOverDAO.exist(id);

		return count > 0 ? true : false;
	}

	@Override
	public List<WorkOver> list() {
		// TODO Auto-generated method stub
		return workOverDAO.list();
	}

	@Override
	public Page<WorkOver> pageSearch(Map<String, Object> searchParams, int pageNumber, int pageSize,boolean count,List<Sort> sortList) {
        Page<WorkOver> page = PageHelper.startPage(pageNumber,pageSize,count).doSelectPage(()->{
            workOverDAO.search(searchParams,sortList);
        });

        return page;
	}

	@Override
	public void approvalWorkOver(PersonInfo personInfo, String ids, String status, String approvalContent) throws Exception {
		List<String> idList = Arrays.asList(ids.split(","));
		for (String id : idList){
			WorkOver workOver = get(id);

			if ("0".equals(workOver.getStatus())){

				//申请人
				PersonPopedom personPopedom = personPopedomService.get(workOver.getPersonPopedomId());
				PersonInfo person = personInfoService.get(personPopedom.getPersonId());

				if (!workOver.getApprovalPersonPopedomId().equals(personInfo.getPopedom())) {
					throw new Exception("无权审核");
				}
				String approvalPersonIdStr = workOver.getApprovalPersonIdStr();
				String approvalStatusStr = workOver.getApprovalStatusStr();
				String approvalTimeStr = workOver.getApprovalTimeStr();
				String approvalContentStr = workOver.getApprovalContentStr();


				//同意
				if ("1".equals(status)) {
					List<PersonPopedom> personPopedomList = new ArrayList<>();

					String companyId = "";
					//申请人的公司
					CompanyInfo companyInfo = companyInfoService.get(personPopedom.getCompanyId());

					if (!"1".equals(companyInfo.getUnitType())) {

						CompanyInfo parent = null;
						int loopNum = 10;
						int zIndex = 0;
						if (org.apache.commons.lang3.StringUtils.isNotEmpty(companyInfo.getParentId())) {
							parent = companyInfoService.get(companyInfo.getParentId());
						}
						while (parent != null && zIndex < loopNum) {
							ApprovalConfig approvalConfig = approvalConfigService.findByCompanyIdAndType(companyInfo.getId(), "5");
							if (approvalConfig != null){
								companyId = companyInfo.getId();
								break;
							}else if (org.apache.commons.lang3.StringUtils.isBlank(companyInfo.getParentId())) {
								break;
							}else {
								parent = companyInfoService.get(parent.getParentId());
								companyInfo = companyInfoService.get(companyInfo.getParentId());
								zIndex++;
							}
						}

						/*CompanyInfo parent = null;
						int loopNum = 10;
						int zIndex = 0;

						if (StringUtils.isNotEmpty(companyInfo.getParentId())) {
							parent = companyInfoService.get(companyInfo.getParentId());
						}
						while (parent != null && zIndex < loopNum) {

							if ("1".equals(parent.getUnitType())) {
								//如果是单位类型是公司或没有上级单位，则不再往上级查找
								companyId = parent.getId();
								break;
							}
							else if (StringUtils.isEmpty(companyInfo.getParentId())){
								break;
							}
							else {
								parent = companyInfoService.get(parent.getParentId());
								zIndex++;
							}
						}*/


					} else {
						companyId = companyInfo.getId();
					}

					//默认审核层级
					int level = 2;

					if (StringUtils.isNotBlank(companyId)){

						ApprovalConfig approvalConfig = approvalConfigService.findByCompanyIdAndType(companyId,"5");
						if (approvalConfig != null){
							level = Integer.valueOf(approvalConfig.getLevel());
						}

					}

					//计算当前审核的是第几级审批
					int nowLevel = 1;
					if (StringUtils.isNotBlank(approvalPersonIdStr)){
						nowLevel = nowLevel + Arrays.asList(approvalPersonIdStr.split(",")).size();
					}
					//判断已审核人总数和需要审核级数
					if (nowLevel<level){
						List<PersonPopedom> dataList =  personPopedomService.findApprovalList(personInfo,null,null,null);
						if (dataList.size()>0){
							personPopedomList.add(dataList.get(0));
						}

					}

					//判断审批人数量,审批人数据为0，审批流程走完
					if (personPopedomList.size() == 0) {
						workOver.setApprovalTime(new Date());
						workOver.setStatus(status);
						workOver.setApprovalContent(approvalContent);
						workOver.setUpdateBy(personInfo.getPopedom());
						workOver.setUpdateTime(new Date());
						update(workOver);

						//申请人添加加班工时
						int oldHours = personPopedom.getWorkOverTime();
						personPopedom.setWorkOverTime(oldHours + workOver.getHours());
						personPopedomService.update(personPopedom);


					}
					//审批人数据不为0
					else {
						PersonPopedom personPopedom1 = personPopedomList.get(0);
						if (StringUtils.isNotBlank(approvalPersonIdStr)) {
							workOver.setApprovalPersonIdStr(approvalPersonIdStr + "," + workOver.getApprovalPersonPopedomId());
							workOver.setApprovalStatusStr(approvalStatusStr + "," + status);
							workOver.setApprovalTimeStr(approvalTimeStr + "," + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"));
							workOver.setApprovalContentStr(approvalContentStr + "," + approvalContent);
						} else {
							workOver.setApprovalPersonIdStr(workOver.getApprovalPersonPopedomId());
							workOver.setApprovalStatusStr(status);
							workOver.setApprovalTimeStr(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"));
							workOver.setApprovalContentStr(approvalContent);
						}

						workOver.setApprovalPersonPopedomId(personPopedom1.getId());
						workOver.setStatus("0");
						workOver.setApprovalContent("");
						workOver.setApprovalTime(null);
						update(workOver);

						new Thread(() -> {
							PersonInfo approvalPerson = personInfoService.get(personPopedom1.getPersonId());

							String typeN = "加班申请";
							String url = "master/extraWork/verifyInfo?id=";

							String accessToken = JwtUtil2.createToken(jwtSecret, approvalPerson.getId() + "", DateTime.now().plusHours(30*24).toDate());
							WechatMessageUtil.sendEvenMessage(approvalPerson.getOpenId(), "有一条新的" + typeN + "信息待审核", person.getName(), workOver.getApprovalNo(), "前往处理", wxConfig.getPortalUrl() + url + workOver.getId() + "&wx=1&exchange=1&role_id=" + personPopedom1.getId() + "&token=" + accessToken, wxConfig.getAppId(), wxConfig.getAppSecret());

						}).start();


					}

					//     }


				}
				//拒绝
				if ("2".equals(status)) {
					workOver.setApprovalTime(new Date());
					workOver.setStatus(status);
					workOver.setApprovalContent(approvalContent);
					workOver.setUpdateBy(personInfo.getPopedom());
					workOver.setUpdateTime(new Date());
					update(workOver);

				}

				//通知申请人

				if (!"0".equals(workOver.getStatus())) {
					new Thread(() -> {
						String firstMessage = "";
						if ("1".equals(workOver.getStatus())) {
							firstMessage = "审核通过";

						}
						if ("2".equals(workOver.getStatus())) {
							firstMessage = "审核拒绝";
						}


						String url = "master/extraWork/info?id=";


						String accessToken = JwtUtil2.createToken(jwtSecret, person.getId() + "", DateTime.now().plusHours(30*24).toDate());
						WechatMessageUtil.sendExamine(person.getOpenId(), firstMessage, person.getName(), workOver.getStatus(), workOver.getStatusN(), "加班", "前往查看", wxConfig.getPortalUrl() +url + workOver.getId() + "&wx=1&exchange=1&role_id=" + personPopedom.getId() + "&token=" + accessToken, wxConfig.getAppId(), wxConfig.getAppSecret());

					}).start();
				}
			}
		}
	}

	@Override
	public String workOverPathSubmit(PersonPopedom personPopedom, Integer hours, String startTime, String endTime, String reason,String personIds, String formId,String type,String ids,String draft,String processTemplateId) throws Exception {

		if (hours<=0){
			throw new Exception("加班时间有误");
		}

		if (StringUtils.isBlank(type)){
			throw new Exception("加班类型错误");
		}

		WorkOver workOver = new WorkOver();
		if(StringUtils.isNotEmpty(ids)){
			workOver=workOverDAO.get(ids);
		}else{
			workOver = new WorkOver();
			workOver.setId(UUID.randomUUID().toString());
		}

		workOver.setPersonPopedomId(personPopedom.getId());
		workOver.setStartTime(DateUtil.parse(startTime));
		workOver.setEndTime(DateUtil.parse(endTime));
		workOver.setHours(hours);
		workOver.setType(type);
		if ("3".equals(type)){
			workOver.setStatus("4");
		}else {
			workOver.setStatus("-99");
		}

		/*if (StringUtils.isNotBlank(personIds)){
			workOver.setType("2");
		}else {
			workOver.setType("1");
		}*/

		workOver.setReason(reason);
		workOver.setCreateTime(new Date());

		if(StringUtils.isNotEmpty(ids)){
			update(workOver);
		}else {
			insert(workOver);
		}

		List<String> personIdList = new ArrayList<>();
		if ("batchExtraWork".equals(formId)){
			personIdList = Arrays.asList(personIds.split(","));
			if (personIdList.size() == 0){
				throw new Exception("请选择人员");
			}
		}
		if ("extraWork".equals(formId)){
			personIdList.add(personPopedom.getPersonId().toString());
		}

		List<PersonInfo> personInfoList = new ArrayList<>();

		workOverPersonService.deletePerson(ids);

		for (String personId : personIdList){
			PersonInfo personInfo = personInfoService.get(Long.parseLong(personId));

			if (personInfo != null){
				WorkOverPerson workOverPerson = new WorkOverPerson();
				workOverPerson.setId(UUID.randomUUID().toString());
				workOverPerson.setWorkOverId(workOver.getId());
				workOverPerson.setPersonPopedomId(personInfo.getPopedom());
				workOverPerson.setCreateTime(new Date());

				//如果加班开始时间<加班申请时间，说明是补加班
				if (workOver.getStartTime().before(workOver.getCreateTime())){
					//直接设置实际加班开始时间=申请加班开始时间
					workOverPerson.setBeginTime(workOver.getStartTime());
				}
				else {
					//如果加班开始时间前半小时单天人员有班次，则也设置实际加班开始时间=申请加班开始时间
					DateTime startDay = new DateTime(workOver.getStartTime()).withTimeAtStartOfDay();
					DateTime earlyTime = new DateTime(workOver.getStartTime()).plusMinutes(-30);

					WorkPersonScheduling workPersonScheduling = workPersonSchedulingService.findByPersonIdSchedulingDay(personInfo.getId(), startDay.toDate());

					if(workPersonScheduling!=null) {
						String shiftIds = workPersonScheduling.getShiftIds();

						if(StringUtils.isNotEmpty(shiftIds)){
							String[] shiftIdArr = shiftIds.split(",");

							SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

							boolean exist = false;

							for (String shiftId : shiftIdArr) {
								try {
									WorkShiftInfo workShiftInfo = workShiftInfoService.get(shiftId);

									Date workTime = sdf.parse(startDay.toString("yyyy-MM-dd") + " " + workShiftInfo.getWorkTime());
									Date closingTime = sdf.parse(startDay.toString("yyyy-MM-dd") + " " + workShiftInfo.getClosingTime());

									if (workTime.compareTo(earlyTime.toDate()) <= 0 && closingTime.compareTo(earlyTime.toDate()) >= 0) {
										exist = true;
										break;
									}
								}
								catch (Exception ex){
									log.error(ex.getMessage(),ex);
								}
							}

							if(exist){
								//直接设置实际加班开始时间=申请加班开始时间
								workOverPerson.setBeginTime(workOver.getStartTime());
							}
						}
					}
				}

				workOverPersonService.insert(workOverPerson);
				personInfoList.add(personInfo);
			}
		}

		if ("1".equals(draft)) {
			//非上级安排的需要加入审核流程
			if (!"3".equals(type)) {
				//创建审核流程id
				String procinstId = procinstService.addProcInst(workOver.getId(),"加班", formId, personPopedom, null,processTemplateId,null);

				workOver.setProcinstId(procinstId);
				workOver.setStatus("0");
				update(workOver);

				ProcinstActivity procinstActivity = procinstActivityService.findByActivityIndexAndProcinstId(1, procinstId);

				if (procinstActivity != null) {
					List<ProcinstActUser> procinstActUserList = procinstActUserService.findByProcinstActivityIdActionType(procinstActivity.getId(), "0", "1");
					if (procinstActUserList.size() > 0) {

						WorkOver finalWorkOver = workOver;
						new Thread(() -> {
							for (ProcinstActUser procinstActUser : procinstActUserList) {
								try {
									PersonInfo personInfo = personInfoService.get(Long.parseLong(procinstActUser.getUserId()));

									//提交人
									PersonInfo personInfo1 = personInfoService.get(personPopedom.getPersonId());
									String accessToken = JwtUtil2.createToken(jwtSecret, personInfo.getId() + "", DateTime.now().plusHours(30 * 24).toDate());
									WechatMessageUtil.sendEvenMessage(personInfo.getOpenId(), "有一条新的加班信息待审核", personInfo1.getName(), com.jpsoft.shinestar.modules.common.utils.StringUtils.getApprovalNo(), "前往处理", wxConfig.getPortalUrl() + "xsy/approval/infosp?id=" + finalWorkOver.getId() + "&procinstActUserId=" + procinstActUser.getId() + "&formId=" + formId + "&token=" + accessToken, wxConfig.getAppId(), wxConfig.getAppSecret());
								} catch (Exception ex) {
									ex.printStackTrace();
								}

							}
						}).start();

					}
				}
			} else {
				if (personInfoList.size() > 0) {
					WorkOver finalWorkOver1 = workOver;
					new Thread(() -> {
						for (PersonInfo personInfo : personInfoList) {
							try {
								String accessToken = JwtUtil2.createToken(jwtSecret, personInfo.getId() + "", DateTime.now().plusHours(30 * 24).toDate());
								WechatMessageUtil.sendExamine(personInfo.getOpenId(), "安排加班", personInfo.getName(), "1", "上级安排", "加班", "前往查看", wxConfig.getPortalUrl() + "xsy/approval/info?id=" + finalWorkOver1.getId() + "&formId=" + formId + "&token=" + accessToken, wxConfig.getAppId(), wxConfig.getAppSecret());
							} catch (Exception ex) {
								ex.printStackTrace();
							}
						}
					}).start();
				}
			}
		}



		return workOver.getId();
	}

	@Override
	public int findSumHoursByParams(Long personId, Date startDate, Date endDate,Map<String, Object> searchParams){
		return workOverDAO.findSumHoursByParams(personId,startDate,endDate,searchParams);
	}

	@Override
	public List<String> findPeopdomId(Date startDate, Date endDate){
		return workOverDAO.findPeopdomId(startDate, endDate);
	}

	@Override
	public int findCountByPersonId(Long personId,Date startDate, Date endDate){
		return workOverDAO.findCountByPersonId(personId,startDate, endDate);
	}

	@Override
	public Date findTopCreateTimeByPersonId(Long personId,Date startDate, Date endDate){
		return workOverDAO.findTopCreateTimeByPersonId(personId,startDate, endDate);
	}

	@Override
	public Date findTopApprovalTimeByPersonId(Long personId,Date startDate, Date endDate){
		return workOverDAO.findTopApprovalTimeByPersonId(personId,startDate, endDate);
	}

	@Override
	public boolean punchIn(String deviceNo, Long personId, Date recordTime) {
		boolean result = false;

		try {
			//查询当前打卡时间是否在加班时段内
			WorkOverPerson workOverPerson = workOverPersonService.findOneByPersonIdAndOffsetMinute(personId, recordTime, -60, 120);

			if(workOverPerson!=null) {
				WorkOver workOver = workOverService.get(workOverPerson.getWorkOverId());

				//记录加班人员加班完成时间
				if (workOverPerson != null && workOver != null) {
					if (workOverPerson.getBeginTime() == null) {
						workOverPerson.setBeginTime(recordTime);
					} else {
//						if (recordTime.before(workOverPerson.getBeginTime())) {
//							workOverPerson.setBeginTime(recordTime);
//						}
						if (workOverPerson.getFinishTime() == null) {
							if(recordTime.after(new DateTime(workOverPerson.getBeginTime()).plusMinutes(30).toDate())) {
								workOverPerson.setFinishTime(recordTime);
							}
						} else if (recordTime.after(workOverPerson.getFinishTime())) {
							workOverPerson.setFinishTime(recordTime);
						}
					}

					if (workOverPerson.getBeginTime() != null && workOverPerson.getFinishTime() != null) {
						int minutes = (int) Minutes.minutesBetween(new DateTime(workOverPerson.getBeginTime()), new DateTime(workOverPerson.getFinishTime())).getMinutes();
						workOverPerson.setDuration(minutes);

						int intHours = minutes / 60;
						int intMinutes = minutes % 60;
						workOverPerson.setDurationStr(intHours + "小时" + intMinutes + "分钟");
					}

					workOverPerson.setUpdateTime(new Date());
					workOverPersonService.update(workOverPerson);
				}

				//查询半小时前是否有加班,有时会有两个加班连起来
				DateTime startTime = new DateTime(workOver.getStartTime());
				WorkOverPerson prevWorkOverPerson = workOverPersonService.findOneByPersonIdAndDate(personId, startTime.plusMinutes(-30).toDate());

				if(prevWorkOverPerson!=null){
					WorkOver prevWorkOver = workOverService.get(prevWorkOverPerson.getWorkOverId());

					if(prevWorkOver!=null){
						if(prevWorkOverPerson.getBeginTime()==null){
							prevWorkOverPerson.setBeginTime(prevWorkOver.getStartTime());
						}

						if(prevWorkOverPerson.getFinishTime()==null) {
							workOverPerson.setFinishTime(prevWorkOver.getEndTime());
						}

						int minutes = (int) Minutes.minutesBetween(startTime, new DateTime(workOverPerson.getFinishTime())).getMinutes();
						prevWorkOverPerson.setDuration(minutes);

						int intHours = minutes / 60;
						int intMinutes = minutes % 60;
						prevWorkOverPerson.setDurationStr(intHours + "小时" + intMinutes + "分钟");
						prevWorkOverPerson.setUpdateTime(new Date());

						workOverPersonService.update(prevWorkOverPerson);
					}
				}

				result = true;
			}
		}
		catch (Exception ex){
			result = false;
			log.error(ex.getMessage(),ex);
		}

		return result;
	}
}