package com.goafanti.common.task;


import com.goafanti.common.bo.EmailBo;
import com.goafanti.common.bo.ErrorDunListBo;
import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.dao.*;
import com.goafanti.common.enums.NoticeStatus;
import com.goafanti.common.model.PaymentNode;
import com.goafanti.common.model.TArrearsDun;
import com.goafanti.common.model.TOrderMid;
import com.goafanti.common.model.TOrderNew;
import com.goafanti.common.utils.AsyncUtils;
import com.goafanti.common.utils.LoggerUtils;
import com.goafanti.order.bo.*;
import com.goafanti.order.enums.OrderDunProjectType;
import com.goafanti.order.service.LegalAffairsService;
import com.goafanti.order.service.NewOrderDunService;
import com.goafanti.order.service.OrderNewService;
import com.goafanti.order.service.OrderProjectService;
import com.goafanti.organization.bo.OutPaymentNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


@Component
//@RestController
public class OrderDunTask {
	@Autowired
	private OrderNewService orderNewService;
	@Autowired
	private NewOrderDunService  newOrderDunService;
	@Autowired
	private TOrderNewMapper	tOrderNewMapper;
	@Autowired
	private TArrearsDunMapper	tArrearsDunMapper;
	@Autowired
	private TOrderMidMapper	tOrderMidMapper;
	@Autowired
	private AdminMapper adminMapper;
	@Autowired
	private PaymentNodeMapper	paymentNodeMapper;
	@Autowired
	private OrderProjectService	orderProjectService;
	@Autowired
	private LegalAffairsService legalAffairsService;

	@Value(value = "${dev.name}")
	private String devName=null;
	@Autowired
	private AsyncUtils	asyncUtils;
	Logger	logger	= LoggerFactory.getLogger(OrderDunTask.class);

	/**
	 * 	每天凌晨3点轮
	 */
//	@ResponseBody
	@Scheduled(cron = "0 0 3  * * ?")
//	@RequestMapping(value = "/open/test", method = RequestMethod.GET)
//	@Scheduled(cron = "0 47 11  * * ?")
	@Transactional(rollbackFor=Exception.class)
	public void startTask() throws InterruptedException {
		updateNewOrderDun();
		Thread.sleep(2000);
		updatePaymentNode();
		Thread.sleep(2000);
//		暂时关闭服务移交
//		pushLegalAffairs();
	}

	/**
	 * 法务订单催款处理
	 */
//	@RequestMapping(value = "/open/pushLegalAffairs", method = RequestMethod.GET)
	public void pushLegalAffairs() {
		InputOrderListBo in = new InputOrderListBo();
		in.setType(0);
		in.setLegalAffairs(0);
		List<OutOrderLegalAffairsListBo>  list=legalAffairsService.getLegalAffairsOrder(in);
		ArrayList<String> addList = new ArrayList<>();
		Date now=new Date();
		for (OutOrderLegalAffairsListBo out : list) {
			Long l=out.getDunStartTime().getTime()+AFTConstants.DUN_START_LIMIT_MS;
			if (l<now.getTime()){
				addList.add(out.getOrderNo());
			}
		}
		List<String> addList2=new ArrayList<>();
		if (!addList.isEmpty())
		for (int i=0;i<addList.size();i++){
			addList2.add(addList.get(i));
			if (50 == addList2.size() || i == addList.size() - 1){
				tOrderMidMapper.updateByList(addList2);
				legalAffairsService.addLagalAffairsLogList(addList2);
				addList2.clear();
			}

		}
	}

	/**
	 * 询处理需要新催款的信息
	 */
//	@RequestMapping(value = "/open/updateNewOrderDun", method = RequestMethod.GET)
	public void updateNewOrderDun(){
  		try {
  			LoggerUtils.debug(logger, "======================新催款任务轮询启动===================");
			List<OutNewOrderDunBo> list= newOrderDunService.selectAllOrderDun();
			Calendar now=Calendar.getInstance();
			Calendar create=Calendar.getInstance();
			Date date =new Date();
			for (OutNewOrderDunBo o : list) {
				now.setTime(date);
				create.setTime(o.getCreateTime());
				//计算特批首期款 特批通过 为催款为首期款 催款时间不为空则计算触发
				if (o.getApproval()!=null&& o.getApproval()==2&& o.getDunType()==1&&o.getWaitDay()!=null) {
					create.add(Calendar.DATE, o.getWaitDay());
					updateOrderDun(o,now,create);
				//会员-期限计算
				}else if(o.getProjectType().equals(OrderDunProjectType.HY.getCode())&&o.getDunType()==2) {
					create.add(Calendar.DATE, o.getEffectiveCount()*180);
					CalendarTimeCleared(create);
					updateOrderDun(o,now,create);
				//财税-期限 计算时间
				} else if(o.getProjectType().equals(OrderDunProjectType.CS.getCode())&&o.getDunType()==2) {
					//获取年
					int year = create.get(Calendar.YEAR);
					//获取月份，0表示1月份
					int month = create.get(Calendar.MONTH) + 1;
					if(month<10)year=year+1;
					if(month>9)year=year+2;
					create.set(year, 5, 1);
					CalendarTimeCleared(create);
					updateOrderDun(o,now,create);
				//自定义 超过设置的时间则触发
				}else if (o.getDunType()==0) {
						CalendarTimeCleared(now);
						//会员提前2个月多一个催款
					if (o.getMemberType()==1){
						pushMamberProject(o,now);
					}
					create.setTime(o.getCustomizeTime());
					updateOrderDun(o,now,create);

				}
			}
			//校准
			calibrationDun();
	} catch (Exception e) {
  			EmailBo emailBo = new EmailBo( "催款处理失败",  AFTConstants.ADMIN_EMAIL, "平台",  "超管");
  			asyncUtils.send(emailBo);
			LoggerUtils.error(getClass(), "===================新催款的信息处理失败======================", e);
		}
  	}

	/**
	 * 此会员催款，只会在当天触发
	 * @param o
	 * @param now
	 */
	private void pushMamberProject(OutNewOrderDunBo o, Calendar now) {
		Calendar start=Calendar.getInstance();
		start.setTime(o.getCustomizeTime());
		start.add(Calendar.MONTH,-2);
		CalendarTimeCleared(start);
		if (now.getTimeInMillis()==start.getTimeInMillis()){
			orderNewService.addTimingTaskNewDunNoticAndSendEmail( o,1);
		}
	}


	/**
	 * 如果有不对的数据就校准数据
	 */
	private void calibrationDun() {
		List<ErrorDunListBo> el = tOrderMidMapper.selectErrorDun();
		if (!el.isEmpty()){
			StringBuffer sb=new StringBuffer();
			for (ErrorDunListBo e : el) {
				sb.append(e.toString());
			}
			EmailBo emailBo=new EmailBo("催款异常核对",AFTConstants.ADMIN_EMAIL,sb.toString());
			asyncUtils.send(emailBo);
			tOrderMidMapper.updateErrorDun();
		}
	}


	/**
	 * 处理付款催款
	 */
	private void updatePaymentNode() {
		LoggerUtils.debug(logger, "======================催款任务结束,付款催款开始===================");
		Calendar now=Calendar.getInstance();
  		Calendar now2=Calendar.getInstance();
  		try {
  		List<OutPaymentNode> list2=paymentNodeMapper.selectByStatus(0);
  		for (OutPaymentNode pn : list2) {
  			now2.setTime(pn.getCreateTime());
  			if(pn.getProjectType().equals(OrderDunProjectType.HY.getCode())&&pn.getDunType()==2) {
  				now2.add(Calendar.DATE, pn.getEffectiveCount()*180);
  				CalendarTimeCleared(now2);
  			}else if(pn.getProjectType().equals(OrderDunProjectType.CS.getCode())&&pn.getDunType()==2) {
  				//	获取年
  				int year = now2.get(Calendar.YEAR);
  		        //获取月份，0表示1月份
  		        int month = now2.get(Calendar.MONTH) + 1;
  		        if(month<10)year=year+1;
  		        if(month>9)year=year+2;
  		        now2.set(year, 5, 1);
  		        CalendarTimeCleared(now2);

  			}else if (pn.getDunType()==0) {
  	  		now2.setTime(pn.getPartyTime());
  	  		CalendarTimeCleared(now);
  	  		}
			if (now.getTimeInMillis() > now2.getTimeInMillis()) {//当前时间大于计算后时间则触发
				updatePaymentNode(pn);
				Thread.sleep(1000);
			}
  		}
  		} catch (InterruptedException e) {
  			LoggerUtils.error(getClass(), "===========================付款催款失败==========================", e);
		}
	}

	/**
	* 	每月1号凌晨4点轮询处理需要欠款催款的信息
	*
	*/
	@Scheduled(cron = "0 0 4 1 * ?")
//	@Scheduled(cron = "0 33 9 * * ?")
//	@RequestMapping(value = "/open/pushOrderArrearsDun", method = RequestMethod.GET)
	public void pushOrderArrearsDun() {
    try {
        LoggerUtils.debug(logger, "======================欠款催款启动===================");
        Date date = new Date();

        List<TArrearsDun> list = tArrearsDunMapper.selectStatusAll(0);
        List<TArrearsDun> list2 = tArrearsDunMapper.selectStatusAll(1);
        List<TArrearsDun> list3 = tArrearsDunMapper.selectStatusAndAmount(2);

        processList(list, date);
        processList(list2, date);
        processList(list3, date);

        LoggerUtils.debug(getClass(), "===========================欠款催款完成==========================");
    } catch (Exception e) {
        LoggerUtils.error(getClass(), "===========================欠款催款失败==========================", e);
    }
}

private void processList(List<TArrearsDun> tarrearsList, Date date) {
    for (TArrearsDun ta : tarrearsList) {
        TOrderMid tm = tOrderMidMapper.selectByOrderNo(ta.getOrderNo());
        TOrderNewBo b = tOrderNewMapper.getSaleIdByOno(ta.getOrderNo());

        if (b == null || b.getDeleteSign() == null || b.getDeleteSign() == 1) {
            ta.setDunStatus(3);
            ta.setEndTime(date);
            ta.setOrderArrears(tm.getOrderArrears());
            tArrearsDunMapper.updateByPrimaryKeySelective(ta);
        } else {
            BigDecimal arrears = tm.getOrderArrears();
            if (arrears.compareTo(BigDecimal.ZERO) > 0) {
                // 欠款大于0则触发邮件并新建记录
				//把旧的停止
                ta.setDunStatus(3);
                tArrearsDunMapper.updateByPrimaryKeySelective(ta);
                ta.setId(null);
                ta.setDunStatus(1);
                ta.setStartTime(date);
                ta.setOrderArrears(arrears);
                ta.setOrderReceivables(tm.getOrderReceivables());
				//新建一条新的
                tArrearsDunMapper.insertSelective(ta);
                orderNewService.addNotic(NoticeStatus.ORDER_ARREARS_DUN.getCode(), b, null);
            } else if (arrears.compareTo(BigDecimal.ZERO) <= 0) {
                ta.setDunStatus(2);
                ta.setOrderArrears(arrears);
                ta.setOrderReceivables(tm.getOrderReceivables());
                tArrearsDunMapper.updateByPrimaryKeySelective(ta);
            }
        }

        // 若确实需要限流，请使用异步方式替代 Thread.sleep()
        // Thread.sleep(200); // 建议删除或改为异步处理
    }
}


//	/**
//	*	旧催款处理
//	*
//	*/
//	public void updateorderDun(){
//  		try {
//  			LoggerUtils.debug(logger, "======================催款任务轮询启动===================");
//  		List<OrderDunTaskBo> list=orderNewService.selectAllOrderDun();
//  		for (OrderDunTaskBo t : list) {
//			if (t.getDunSubject()/10==1) {//1则为订单催款信息否则为项目催款信息
//				if (t.getDunSubject()%10==t.getOrderStatus()&&t.getSettlementAmount().compareTo(t.getMoney()) == -1) {
//					 updateOrderDun(t);
//						Thread.sleep(2000);
//				}
//			}else {
//				if (t.getDunSubject()%10>=t.getProjectStatus()&&t.getSettlementAmount().compareTo(t.getMoney()) == -1) {
//					 updateOrderDun(t);
//					 Thread.sleep(2000);
//				}
//			}
//		}
//  		} catch (Exception e) {
//			LoggerUtils.error(getClass(), "==========================催款的信息处理失败==========================", e);
//		}
//
//  	}



	private void updatePaymentNode(OutPaymentNode pn) {
		PaymentNode p=new PaymentNode();
		p.setId(pn.getId());
		p.setDunStatus(1);
		p.setStartTime(new Date());
		paymentNodeMapper.updateByPrimaryKeySelective(p);
		orderProjectService.addNoticAndEmail(pn,NoticeStatus.PAYMENT_DUN.getCode());
	}




	private void CalendarTimeCleared(Calendar now) {
		now.set(Calendar.HOUR_OF_DAY, 0);
	    now.set(Calendar.MINUTE, 0);
	    now.set(Calendar.SECOND, 0);
	    now.set(Calendar.MILLISECOND, 0);
	}

	/**
	 * 定时催款触发
	 * 如果当前时间大于等于触发时间才触发流程
	 * @param t
	 * @param now 当前时间
	 * @param now2 触发时间
	 */
	private void updateOrderDun(OutNewOrderDunBo t,Calendar now,Calendar now2) {
		if (now.getTimeInMillis() >= now2.getTimeInMillis()) {
			InputNewOrderDunBo o=new InputNewOrderDunBo();
			TOrderNew orderNew=tOrderNewMapper.queryById(t.getOrderNo());
			Date date = new Date();
			o.setId(t.getId());
			o.setStatus(1);
			o.setStartTime(date);
			if (t.getMoney()==null)t.setMoney(new BigDecimal(0));
			newOrderDunService.updateDun(o);
			TOrderMid tm=orderNewService.pushOrderMidDun(t.getOrderNo(),orderNew.getSettlementAmount(),date);
			TArrearsDun td=new TArrearsDun();
			td.setOrderArrears(tm.getOrderArrears());
			td.setOrderReceivables(tm.getOrderReceivables());
			if (tArrearsDunMapper.checkOrderNo(t.getOrderNo(),null)<1) {
				td.setOrderNo(t.getOrderNo());
				tArrearsDunMapper.insertSelective(td);
			}else if(tArrearsDunMapper.checkOrderNo(t.getOrderNo(),0)>0){
				Integer i=tArrearsDunMapper.selectByStatus(t.getOrderNo(), 0);
				td.setId(i);
				tArrearsDunMapper.updateByPrimaryKeySelective(td);
			}
			orderNewService.addTimingTaskNewDunNoticAndSendEmail( t,0);
			orderNewService.pushOrderDunContent(orderNew);
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}


}
