package com.goafanti.common.task;

import com.goafanti.business.bo.OutRestrictProject;
import com.goafanti.common.bo.EmailBo;
import com.goafanti.common.bo.userDaysBo;
import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.dao.NoticeMapper;
import com.goafanti.common.dao.RestrictProjectMapper;
import com.goafanti.common.dao.UserMapper;
import com.goafanti.common.dao.UserTransferLogMapper;
import com.goafanti.common.enums.NoticeStatus;
import com.goafanti.common.enums.NoticeTypes;
import com.goafanti.common.model.Notice;
import com.goafanti.common.model.User;
import com.goafanti.common.model.UserTransferLog;
import com.goafanti.common.utils.AsyncUtils;
import com.goafanti.common.utils.LoggerUtils;
import com.goafanti.common.utils.StringUtils;
import com.goafanti.customer.bo.LockingReleaseBo;
import com.goafanti.customer.service.CustomerService;
import com.goafanti.user.service.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;


@Component
//@RestController
public class ReleaseUserTask {
	@Resource
	private CustomerService customerService;
	@Resource
	private UserService userService;
	@Resource
	private NoticeMapper	noticeMapper;
	@Resource
	private AsyncUtils	asyncUtils;
	@Value(value = "${dev.name}")
	private String devName=null;


	int pointsDataLimit = 50;



	@Resource
	private RestrictProjectMapper restProjectMapper;

	@Resource
	private UserTransferLogMapper userTransferLogMapper;
	@Resource
	private UserMapper userMapper;

	/**
	 * 客户释放
	 *
	 */
//	@Scheduled(cron = "0 43 15  * * ?")
//	@RequestMapping("/open/test")
	@Scheduled(cron = "0 0 1  * * ?")
	public void startTask() {
		try {
			List<User> userList = userService.selectUserByRoleName("营销员", "营销经理");
			pushUserDays(userList);
			Thread.sleep(500);
			updateUser(userList);
			Thread.sleep(500);
			pushRestrictProject(userList);
			Thread.sleep(500);
			pushReleaseClueUser(userList);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	private void pushReleaseClueUser(List<User> userList) {
		LoggerUtils.debug(getClass(), "==============线索客户丢失开始============");
		LocalDateTime now = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
		Date date = new Date();
		List<Notice> ln = new ArrayList<>();
		List<User> releaseUserList = new ArrayList<>();
		List<UserTransferLog> logList=new ArrayList<>();
		for (User admin : userList) {
			List<User> users = userMapper.selectClueUserByClueType(admin.getId());
			for (User u : users) {
				String aid=null;
				LocalDateTime clueTime=u.getClueTransferTime().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime();
				clueTime = clueTime.withHour(0).withMinute(0).withSecond(0);
				//已分配的通知人与时间不同，
				if (u.getClueProcess()==1){
					aid=u.getAid();
				}else{
					aid=admin.getId();
				}
				LocalDateTime endTime = clueTime.plusDays(AFTConstants.CLUE_USER_MAX);
				long between= ChronoUnit.DAYS.between(now, endTime);
				System.out.println("====="+u.getNickname()+"===="+between);
				if (between<1){
					releaseUserList.add(u);
					logList.add(new UserTransferLog(u.getId(), "1",null, 27, "",date));
					ln.add(new Notice(UUID.randomUUID().toString(),date, 0, aid,
							NoticeStatus.CLUE_USER_RELEASE.getCode(),
							String.format("您的线索客户[%s]已丢失！",u.getNickname())
							,u.getId()));
				}
			}

		}
		addNoticeBatch(ln);
		addUserTransferLogBatch(logList);
		pushClueUserRelease(releaseUserList);
		LoggerUtils.debug(getClass(), "==============线索客户丢失结束============");
	}

	private void pushClueUserRelease(List<User> lu) {
		List<User> updateList=new ArrayList<>();
		if (lu != null && !lu.isEmpty()) {
			for (int i = 0; i < lu.size(); i++) {
				updateList.add(lu.get(i));
				if (50 == updateList.size() || i == lu.size() - 1) {
                    userMapper.updateClueUserRelease(updateList);
                    updateList.clear();
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}

	}


	/**
	 * 限时项目定时任务
	 */
	private void pushRestrictProject(List<User> userList) {
		LoggerUtils.debug(getClass(), "==============限时项目丢失开始============");
		List<Notice> ln = new ArrayList<>();
		List<UserTransferLog> lu=new ArrayList<>();
		LocalDateTime now = LocalDateTime.now();
		Date date = new Date();
		List<Integer> list = new ArrayList<>();
		for (User u : userList) {
			if (StringUtils.isNotBlank(u.getId())) {
				List<OutRestrictProject> rpList = restProjectMapper.selectByUid(u.getId());
				for (OutRestrictProject rp : rpList) {
						LocalDateTime lockTime = rp.getLockTime().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime();
					if (rp.getType()==1){
						LocalDateTime endTime2 = lockTime.plusDays(15);
						long between2 = ChronoUnit.DAYS.between(now, endTime2);
						if (between2==0){
							ln.add(new Notice(UUID.randomUUID().toString(),date, 0, rp.getAid(),
									NoticeStatus.RESTRICT_PROJECT_LOSE30_REMIND.getCode(),
									String.format("您的客户[%s]限时私有项目[%s]还有15天即将丢失！",rp.getUserName(), rp.getProjectName())
									,rp.getUid()));
						}else {
							LocalDateTime endTime = lockTime.plusDays(30);
							long between = ChronoUnit.DAYS.between(now, endTime);
							if (between<1){
								ln.add(new Notice(UUID.randomUUID().toString(),date, 0, rp.getAid(),
										NoticeStatus.RESTRICT_PROJECT_LOSE30.getCode(),
										String.format("您的客户[%s]限时私有项目[%s]已丢失！",rp.getUserName(), rp.getProjectName())
										,rp.getUid()));
								list.add(rp.getId());
								lu.add(new UserTransferLog(rp.getUid(), rp.getAid(), rp.getPid(), 18, "限时项目释放（30天）",date));
							}
						}

					}else if (rp.getType()==2){
						LocalDateTime endTime2 = lockTime.plusDays(255);
						long between2 = ChronoUnit.DAYS.between(now, endTime2);
						if (between2==0){
							ln.add(new Notice(UUID.randomUUID().toString(),date, 0, rp.getAid(),
									NoticeStatus.RESTRICT_PROJECT_LOSE270_REMIND.getCode(),
									String.format("您的客户[%s]限时签单项目[%s]还有15天即将丢失！",rp.getUserName(), rp.getProjectName())
									,rp.getUid()));
						}else{
							LocalDateTime endTime = lockTime.plusDays(270);
							long between = ChronoUnit.DAYS.between(now, endTime);
							if (between<1){
								ln.add(new Notice(UUID.randomUUID().toString(),date, 0, rp.getAid(),
										NoticeStatus.RESTRICT_PROJECT_LOSE270.getCode(),
										String.format("您的客户[%s]限时签单项目[%s]已丢失！",rp.getUserName(), rp.getProjectName())
										,rp.getUid()));
								list.add(rp.getId());
								lu.add(new UserTransferLog(rp.getUid(), rp.getAid(), rp.getPid(), 19, "限时项目释放（270天）",date));
							}
						}

					}
				}
			}

		}
		addNoticeBatch(ln);
		pushReleaseRestrictProject(list);
		addUserTransferLogBatch(lu);
		LoggerUtils.debug(getClass(), "==============限时项目结束============");
	}

	private void addUserTransferLogBatch(List<UserTransferLog> list) {
		List<UserTransferLog> list2 = new ArrayList<>();
		int i=0;
		for (UserTransferLog e : list) {
			i++;
			list2.add(e);
			if(list2.size()==pointsDataLimit||i==list.size()){
				userTransferLogMapper.insertList(list2);
				list2.clear();
			}
		}
	}



	private void pushReleaseRestrictProject(List<Integer> list) {
		List<Integer> list2 = new ArrayList<>();
		int i=0;
		for (Integer e : list) {
			i++;
			list2.add(e);
			if(list2.size()==pointsDataLimit||i==list.size()){
				restProjectMapper.updateRelease(list2);
				list2.clear();
			}
		}
	}

	/**
	 * 客户提醒
	 * @param userList
	 * @throws InterruptedException
	 */
	private void pushUserDays(List<User> userList ) throws InterruptedException {
		LoggerUtils.debug(getClass(), "==============客户提醒开始============");
		List<Notice> ln = new ArrayList<>();
		List<userDaysBo> userChannelList = new ArrayList<userDaysBo>();
		for (User u : userList) {
			if (StringUtils.isNotBlank(u.getId())&&!AFTConstants.CAOJIN_AID.equals(u.getId())) {
				List<userDaysBo> userTmpList  = customerService.selectReleaseUserDays(u.getId());
				for (userDaysBo ub : userTmpList) {
					String str=null;
					if (ub.getChannel() == 0) {
						String shareType="";
						if(ub.getNewChannel()==0&&ub.getType()==0)shareType="私有";
						else if(ub.getNewChannel()==0&&ub.getType()==2)shareType="签单";
						else if(ub.getNewChannel()==1)shareType="渠道";
						str = String.format("您的%s客户【%s】剩余天数不足十五天，请及时%s！", shareType, ub.getName(),"跟进");
					}else {
						str = String.format("您的%s客户【%s】剩余天数不足十五天，请及时签单！", "外联", ub.getName());
					}
					ln.add(new Notice(UUID.randomUUID().toString(), new Date(), 0, ub.getAid(),
							NoticeStatus.CUSTOMER_LOSE_REMINDER.getCode(), str,ub.getUid()));
				}
			}

			//查询15天未跟进，私有跟释放前15天重复，去除
			if (StringUtils.isNotBlank(u.getId())) {
				userChannelList = customerService.selectChannelNotFollow(u.getId());
			}
			for (userDaysBo ub : userChannelList) {
				String str=null;
				if (ub.getChannel() == 1) {
					str = String.format("您的%s客户【%s】已经十五天未跟进，请及时跟进或者限时签单！", "外联", ub.getName());
				}
				ln.add(new Notice(UUID.randomUUID().toString(), new Date(), 0, ub.getAid(),
						NoticeStatus.CUSTOMER_PRIVATE_REMINDER.getCode(), str,ub.getUid()));
			}
		}
		addNoticeBatch(ln);
		LoggerUtils.debug(getClass(), "==============客户提醒结束============");
	}

	/**
	 * 将客户和业务转为待释放
	 */
	public void updateUser(List<User> userList ) {
		LoggerUtils.debug(getClass(), "==============客户释放开始============");
		Date releaseTime = new Date();
		try {
			List<LockingReleaseBo> lockUserList = new ArrayList<>();
			List<LockingReleaseBo> lockSignList = new ArrayList<>();
			if (userList != null && !userList.isEmpty()) {
				for (User u : userList) {
					System.out.println(u.getId());
					if (StringUtils.isNotBlank(u.getId())&&!AFTConstants.CAOJIN_AID.equals(u.getId())) {
						// 获取30天释放 释放以锁定表与user_mid最后跟进取时间
						List<LockingReleaseBo>  userTmpList = customerService.selectWaitReleaseCustomer(u.getId());
						customerService.pushReleaseLog(userTmpList);
						addUserNotice(userTmpList);
						if (!userTmpList.isEmpty()) {
							lockUserList.addAll(userTmpList);
						}
						//获取需要释放的签单客户
						List<LockingReleaseBo> users1 = userService.selectSignReleaseUser(u.getId());
						customerService.pushReleaseLog(users1);
						addUserNotice(users1);
						lockSignList.addAll(users1);
					}
				}
			}
			//签单客户要单独处理，没有锁，直接释放
			pushSignUser(lockSignList);
			//处理私有客户
			pushPrivateUser(lockUserList);
			pushChannel(releaseTime, userList);
			//客户释放
			List<LockingReleaseBo> lockList = customerService.selectPendinglockUserList();
			if (!lockList.isEmpty()){
				customerService.updateReleaseLock(releaseTime);
			}
		} catch (Exception e) {
			Notice n = new Notice(UUID.randomUUID().toString(), new Date(), 0, "1",
					NoticeStatus.TASK_PATENT_ERROR.getCode(), "==============客户释放失败================",null);
			addNotice(n);
			EmailBo emailBo = new EmailBo("释放客户失败", AFTConstants.ADMIN_EMAIL, "平台", "超管");
			asyncUtils.send(emailBo);
			LoggerUtils.error(getClass(), "====================客户释放失败=================");
			LoggerUtils.error(getClass(), "客户释放失败", e);
		}
		LoggerUtils.debug(getClass(), "==============客户释放完成============");
	}




	private void pushPrivateUser(List<LockingReleaseBo> lockUserList) throws InterruptedException {
		List<LockingReleaseBo> newList=new ArrayList<LockingReleaseBo>();
		if (!lockUserList.isEmpty()) {
			for (int i = 0; i < lockUserList.size(); i++) {
				newList.add(lockUserList.get(i));
				if (pointsDataLimit == newList.size() || i == lockUserList.size() - 1) {
					customerService.updatePendingReleaseLock(newList);
					newList.clear();
					Thread.sleep(2000);
				}

			}
		}
	}

	private void pushSignUser(List<LockingReleaseBo> lockSignList) throws InterruptedException {
		List<LockingReleaseBo> newList = new ArrayList<LockingReleaseBo>();
		if (!lockSignList.isEmpty()) {
			for (int i = 0; i < lockSignList.size(); i++) {
				newList.add(lockSignList.get(i));
				if (pointsDataLimit == newList.size() || i == lockSignList.size() - 1) {
					customerService.updateUserShareType(newList);
					newList.clear();
					Thread.sleep(2000);
				}

			}
		}
	}




	/**
	 * 处理外联
	 */
	private void pushChannel(Date releaseTime, List<User> userList) throws InterruptedException {
		// 获取超过90天客户，判断是否回收过，未回收则回收，已回收则释放为公共客户
		List<userDaysBo> userChannelList =null;
		List<userDaysBo> count =new ArrayList<userDaysBo>();
		if (userList != null && !userList.isEmpty()) {
			for (User u : userList) {
				userChannelList=customerService.selectChannelUserDays(u.getId());
				if (userChannelList!=null) {
					count.addAll(userChannelList);
				}
			}
		}
		List<userDaysBo> hsList=new ArrayList<>();
		List<userDaysBo> sfList=new ArrayList<>();
		if (count != null && !count.isEmpty()) {
			for (int i = 0; i < count.size(); i++) {
				//回收
				if (count.get(i).getRecovery()==0) {
					hsList.add(count.get(i));
				}else {
					sfList.add(count.get(i));
				}
				if (pointsDataLimit == (hsList.size()+sfList.size()) || i == count.size() - 1) {
					if(!hsList.isEmpty())userService.pushReleaseUserChannel(hsList,0);
					if(!sfList.isEmpty())userService.pushReleaseUserChannel(sfList,1);
					addChannelNotice(hsList,sfList);
					hsList.clear();
					sfList.clear();
					Thread.sleep(2000);
				}
			}
		}

	}

	public void addNotice(Notice n ) {
		n.setType(NoticeTypes.getType(n.getNoticeType()));
		noticeMapper.insertSelective(n);
	}

	public void addNoticeBatch(List<Notice> ln) {
		List<Notice> newList=new ArrayList<Notice>();
		if (ln != null && !ln.isEmpty()) {
			for (int i = 0; i < ln.size(); i++) {
				ln.get(i).setType(NoticeTypes.getType(ln.get(i).getNoticeType()));
				newList.add(ln.get(i));
				if (50 == newList.size() || i == ln.size() - 1) {
					if (!newList.isEmpty()) {
						//发送站内信
						noticeMapper.insertBatch(newList);
					}
					newList.clear();
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}


	private void addUserNotice(List<LockingReleaseBo> userTmpList) {
		List<Notice> nl=new ArrayList<Notice>();
		if (!userTmpList.isEmpty()) {
			for (LockingReleaseBo u : userTmpList) {
				String str="";
				String str2="";
				String str3="";
				if(u.getNewChannel()==0&&u.getShareType()==0){
					str2="私有";
					str3="或270天未签单";
				}else if(u.getNewChannel()==0&&u.getShareType()==2){
					str2="签单";
				}else if(u.getNewChannel()==1){
					str2= "渠道";
				}
				str=String.format("您的%s客户【%s】已经30天未跟进%s，已经自动释放！", str2, u.getUserName(),str3);
				nl.add(new Notice(UUID.randomUUID().toString(), new Date(), 0, u.getAid(),
						NoticeStatus.CUSTOMER_LOSE30.getCode(),
						str,
						u.getUid()));
			}
		}
		if(!nl.isEmpty())addNoticeBatch(nl);
	}





	private void addChannelNotice(List<userDaysBo> hsList, List<userDaysBo> sfList) {
		List<Notice> nl=new ArrayList<Notice>();
		for (userDaysBo hs : hsList) {
			nl.add(new Notice(UUID.randomUUID().toString(), new Date(), 0, hs.getAid(),
					NoticeStatus.CUSTOMER_CHENNEL_RECOVERY.getCode(),
					String.format("您的%s客户【%s】已经90天未跟进，已经自动回收！", "外联", hs.getName()),
					hs.getUid()));
		}

		for (userDaysBo sf : sfList) {
			nl.add(new Notice(UUID.randomUUID().toString(), new Date(), 0, sf.getAid(),
					NoticeStatus.CUSTOMER_CHENNEL_LOSE.getCode(),
					String.format("您的%s客户【%s】已经90天未跟进，已经自动释放！", "外联", sf.getName()),
					sf.getUid()));
		}
		if(!nl.isEmpty())addNoticeBatch(nl);
	}

}
