package com.goafanti.order.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.mail.MessagingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.goafanti.admin.bo.AdminListBo;
import com.goafanti.common.bo.EmailBo;
import com.goafanti.common.bo.Error;
import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.dao.AdminMapper;
import com.goafanti.common.dao.OrganizationManagementMapper;
import com.goafanti.common.dao.TOrderBackMapper;
import com.goafanti.common.dao.TOrderBillNewMapper;
import com.goafanti.common.dao.TOrderBonusMapper;
import com.goafanti.common.dao.TOrderLogMapper;
import com.goafanti.common.dao.TOrderMonthReportMapper;
import com.goafanti.common.dao.TOrderNewMapper;
import com.goafanti.common.dao.TOrderRefundMapper;
import com.goafanti.common.dao.TOrderTaskMapper;
import com.goafanti.common.enums.NoticeStatus;
import com.goafanti.common.enums.OrderLogProcess;
import com.goafanti.common.error.BusinessException;
import com.goafanti.common.model.Admin;
import com.goafanti.common.model.TOrderBack;
import com.goafanti.common.model.TOrderBillNew;
import com.goafanti.common.model.TOrderBonus;
import com.goafanti.common.model.TOrderLog;
import com.goafanti.common.model.TOrderNew;
import com.goafanti.common.model.TOrderRefund;
import com.goafanti.common.model.TOrderTask;
import com.goafanti.common.utils.LoggerUtils;
import com.goafanti.common.utils.SendEmailUtil;
import com.goafanti.common.utils.StringUtils;
import com.goafanti.core.mybatis.BaseMybatisDao;
import com.goafanti.core.mybatis.page.Pagination;
import com.goafanti.core.shiro.token.TokenManager;
import com.goafanti.order.bo.OrderListBo;
import com.goafanti.order.bo.TOrderNewBo;
import com.goafanti.order.enums.ApprovalNewState;
import com.goafanti.order.enums.BonusSubject;
import com.goafanti.order.enums.OrderNewState;
import com.goafanti.order.enums.ProcessStatus;
import com.goafanti.order.enums.refundState;
import com.goafanti.order.service.FundManageOrderService;
import com.goafanti.order.service.OrderNewService;
import com.goafanti.organization.bo.OrganizationListOut;

@Service
public class FundManagerOrderServiceImpl extends BaseMybatisDao<TOrderNewMapper> implements FundManageOrderService {
	
	@Autowired
	private TOrderNewMapper	tOrderNewMapper;
	@Autowired
	private AdminMapper	adminMapper;
	@Autowired
	private TOrderBillNewMapper billNewMapper;
	@Autowired
	private TOrderBackMapper backMapper;
	@Autowired
	private TOrderRefundMapper refundMapper;
	@Autowired
	private TOrderBonusMapper bonusMapper;
	@Autowired
	private TOrderMonthReportMapper monthReportMapper;
	@Autowired
	private TOrderTaskMapper taskMapper;
	@Autowired
	private TOrderLogMapper	tOrderLogMapper;
	@Autowired
	private OrderNewService orderNewService;
	@Autowired
	private OrganizationManagementMapper	organizationManagementMapper;
	Logger	logger	= LoggerFactory.getLogger(FundManagerOrderServiceImpl.class);
	@SuppressWarnings("unchecked")
	@Override
	public Pagination<OrderListBo> allUnassignedOrder(OrderListBo order, Integer pageNo,
			Integer pageSize) {
		Map<String, Object> params = new HashMap<String, Object>();
		//if (order.getOutsource()==null)order.setOutsource(0);//默认非外包 
		params.put("o", order);
		Pagination<OrderListBo> data = (Pagination<OrderListBo>)findPage("getAllUnassignedListOrder", "getAllUnassignedCountOrder", params, pageNo, pageSize);
		return data;
	}
	
	@Override
	public Integer updateDistributionFinance(String orderNo, String financeId, Integer approval) {
		// 先判断订单id和财务专员是否存在或者能够使用
		//判断是不是特批的数据
		if(approval != ApprovalNewState.TG.getCode() && approval != ApprovalNewState.FTP.getCode()){//特批未通过 2 0
			return -1;
		}
		
		TOrderNew torder=checkDeleteSign(orderNo);
		TOrderNew onew = new TOrderNew();
		onew.setOrderNo(orderNo);
		//onew.setDeleteSign(0);//锁定订单也能走流程
		onew.setApproval(approval);//特批状态
		onew.setProcessStatus(ProcessStatus.YPCWGLY.getCode());//已派财务管理员
		onew.setOrderStatus(OrderNewState.QDSHTG.getCode());//营销管理员审核通过
		int idCount = tOrderNewMapper.getCountByIdAndStatus(onew);
		int fidCount = adminMapper.getCountById(financeId);
		Integer r = null;
		if(idCount == 1 && fidCount == 1){
			//修改订单流程状态
			TOrderNew record = new TOrderNew();
			record.setOrderNo(orderNo);
			record.setFinanceId(financeId);
			if(torder.getProcessStatus()<ProcessStatus.YPZXSGLY.getCode()) {
				record.setProcessStatus(ProcessStatus.YPCWZY.getCode());				
			}
			addOrderLog(orderNo, OrderLogProcess.CWPD.getCode(),null);
			r = tOrderNewMapper.updateByPrimaryKeySelective(record);
		}else{
			//返回错误标志 提示订单编号或者财务专员选择错误
			r = -2;
		}
		return r;
	}
	
	private TOrderNew checkDeleteSign(String orderNo) {
		TOrderNew t=tOrderNewMapper.selectByPrimaryKey(orderNo);
		//if(t.getDeleteSign()==2) throw new BusinessException(new Error(ErrorConstants.ORDER_ALREADY_REVOKE, t.getOrderNo(),""));
		return t;
	}

	public void addOrderLog(String orderNo, Integer code, String reason) {
		TOrderLog tl=new TOrderLog();
		tl.setOrderNo(orderNo);
		tl.setProcess(code);
		tl.setRemarks(reason);
		tl.setAid(TokenManager.getAdminId());
		tOrderLogMapper.insertSelective(tl);
		
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> financeList(OrderListBo order, Integer pageNo, Integer pageSize) {
		Map<String, Object> result = new HashMap<String, Object>();
		Map<String, Object> params = new HashMap<String, Object>();
		List<String> fids=new ArrayList<>();
		if(TokenManager.hasRole(AFTConstants.CED)||TokenManager.hasRole(AFTConstants.APPROVAL_DECISION)||
				TokenManager.hasRole(AFTConstants.VICE_CEO)||TokenManager.hasRole(AFTConstants.FINANCE_ADMIN)||
				TokenManager.hasRole(AFTConstants.SUPERADMIN)) {
			//如果是这些角色则看全部
		}else if(TokenManager.hasRole(AFTConstants.FINANCE_MANAGER)) {
			fids =adminMapper.selectBySuperId(TokenManager.getAdminId());
			params.put("fids", fids);
		} else {
			 fids.add(TokenManager.getAdminId());
			params.put("fids",fids);
		}
		if (order.getOutsource()==null)order.setOutsource(0);//默认非外包 
		params.put("o", order);
		Pagination<OrderListBo> data = (Pagination<OrderListBo>)findPage("financeList", "financeCount", params, pageNo, pageSize);
		result.put("pagination", data);
		Map<String, Object> count = tOrderNewMapper.countTotalAndActually(order,fids);
		result.put("count", count);
		return result;
	}
	
	

	@Override
	public Integer updateReject(TOrderBack back) {
		// 是否已经收款
		TOrderNew t=checkDeleteSign(back.getOrderNo());
		BigDecimal bd = billNewMapper.getAmountByOid(back.getOrderNo());
		if(bd.compareTo(new BigDecimal(0.0)) == 1){
			return 0;//已经收款不能驳回
		}
		TOrderNewBo b = tOrderNewMapper.getSaleIdByOno(back.getOrderNo());//订单和订单负责人相关信息
		if(null == b || StringUtils.isBlank(b.getSalesmanId())){
			return -1;
		}
		//否 可以处理驳回
		
		//修改订单状态
		TOrderNew orderNew = new  TOrderNew();
		orderNew.setOrderNo(back.getOrderNo());
		orderNew.setOrderStatus(OrderNewState.YBH.getCode());
		orderNew.setProcessStatus(ProcessStatus.YPYXY.getCode());
		//设置驳回人为财务、将财务负责人置空
		orderNew.setBackStatus(3);
		orderNew.setFinanceId("");
		int c = tOrderNewMapper.updateByPrimaryKeySelective(orderNew);
		
		//新增驳回数据
		if(c>0){
			back.setBackStatus(0);
			back.setInitiate(TokenManager.getAdminId());//发起人
			back.setAccept(b.getSalesmanId());	//查看该订单的负责人	
			addOrderLog(back.getOrderNo(), OrderLogProcess.BH.getCode(),back.getReason());
			c = backMapper.insertSelective(back);
			List<String> aids = new ArrayList<>();
			aids.add(t.getSalesmanId());;
			if (aids.isEmpty()) {
				throw new BusinessException(new Error( "邮件发送失败，对方设置邮箱错误","邮件发送失败，对方设置邮箱错误")); 
			}
			orderNewService.pushGeneralSendNoticeAndEmail(aids, NoticeStatus.ORDER_NO.getCode(),t.getOrderNo(), TokenManager.getAdminId(),t.getApproval());
		}
		return c;
	}

	@Override
	public Integer addReceiptsFlow(TOrderBillNew billNew, String contractNo) {
		
		//判断有没有要加入的金额有没有超过总金额
		BigDecimal bill = billNewMapper.getAmountByOid(billNew.getOrderNo());
		//获得的单个订单金额数据(首付金额和总金额)
		TOrderNew o = checkDeleteSign(billNew.getOrderNo());
		if(null == o){
			return -2;
		}
		if(o.getDeleteSign()==3)return -3;
		BigDecimal bd = bill.add(billNew.getTransactionAmount().abs());
		//奖金信息
		TOrderBonus bonus = new TOrderBonus();
		bonus.setId(UUID.randomUUID().toString());
		bonus.setOrderNo(billNew.getOrderNo());
		bonus.setGrantBy(TokenManager.getAdminId());
		int lstaus = 0;//如果订单流水小于首付 lstaus 0
		
		// 0 相等
		// -1 小于 
		// 1 大于
		if(bd.compareTo(o.getTotalAmount()) == 1){//如果订单流水总额大于总金额 return -1
			return -1;//超过不能添加
		}else if(bd.compareTo(o.getTotalAmount()) == 0){//付完款//如果订单流水等于于总金额 lstaus 2
			lstaus = 2;
			bonus.setBonusSubject(BonusSubject.WK.getCode());//12
			//发放给技术员如果付完款所有参与这个项目任务的人都会有结算奖
			//获得所有的任务负责人
			List<TOrderTask> l = taskMapper.getReceiverByOid(billNew.getOrderNo());
//			取消没有技术员不能支付全款
//			if(null == l || l.size() == 0){
//				return -3;//没有给将任务分给咨询师(技术员)
//			}
			for (TOrderTask tOrderTask : l) {
				if(null != tOrderTask &&null != tOrderTask.getTaskReceiver()){
					bonus.setTaskId(tOrderTask.getId());//任务id
					bonus.setGrantTarget(tOrderTask.getTaskReceiver());
					bonus.setGrantType(1);
					int c = bonusMapper.checkByOnoAndSub(bonus);
					//不存在就设置
					if(c==0){
						bonus.setId(UUID.randomUUID().toString());
						bonusMapper.insertSelective(bonus);
					}
					
				}
				
			}
			addOrderLog(billNew.getOrderNo(), OrderLogProcess.CWQK.getCode(),billNew.getRemarks());	
		}else if(bd.compareTo(o.getTotalAmount()) == -1){//如果订单流水小于总金额
			if(bd.compareTo(o.getFirstAmount()) == 0 || bd.compareTo(o.getFirstAmount()) == 1){//首付完成
				//查看首付奖是否存在
				TOrderBonus b = new TOrderBonus();
				b.setOrderNo(billNew.getOrderNo());
				b.setBonusSubject(11);
				b.setGrantType(0);
				b.setGrantTarget(o.getSalesmanId());
				int c = bonusMapper.checkByOnoAndSub(b);
				//不存在就设置
				if(c==0){
					bonus.setBonusSubject(BonusSubject.SF.getCode());//11
				}
				lstaus = 1;
				addOrderLog(billNew.getOrderNo(), OrderLogProcess.CWSF.getCode(),billNew.getRemarks());
			}
		}
		//否则新增流水信息
		billNew.setBillNo(UUID.randomUUID().toString().replaceAll("-", ""));
		billNew.setCreater(TokenManager.getAdminId());
		int result = billNewMapper.insertSelective(billNew);
		//修改订单结算金额和结算状态
		//如果已经首付并且流程状态是没有派给咨询师的修改流程状态为4
		TOrderNew orderNew = new TOrderNew();
		orderNew.setOrderNo(billNew.getOrderNo());
		if(contractNo!=null)orderNew.setContractNo(contractNo);
		//这里的已收金额是以前收的所有金额加上本次收的金额
		orderNew.setSettlementAmount(billNew.getTransactionAmount().add(o.getSettlementAmount()));
		orderNew.setLiquidationStatus(lstaus);
		if(result > 0){
			result = tOrderNewMapper.updateByPrimaryKeySelective(orderNew);
			//如果达到奖金发放要求新增奖金信息
			if(null != bonus.getBonusSubject()){
				bonus.setId(UUID.randomUUID().toString());
				bonus.setGrantTarget(o.getSalesmanId());
				//设置发放人类型
				bonus.setGrantType(0);
				bonusMapper.insertSelective(bonus);
			}
		}
		
		return result;
	}

	@Override
	public Integer updateChangeRefund(TOrderRefund refund) {
		//查看当前退单状态
		TOrderRefund d = refundMapper.selectByPrimaryKey(refund.getId());
		if(d.getRefundStatus() != refundState.DSH.getCode()){
			return -1;
		}
		//如果审核通过给咨询师和营销员发起退单通知
		if(refund.getRefundStatus() == refundState.SHTG.getCode()){
			//修改订单状态
			TOrderNewBo o = tOrderNewMapper.agreeEmailData(refund.getId());
			TOrderNew record = new TOrderNew();
			record.setOrderNo(o.getOrderNo());
			record.setOrderStatus(OrderNewState.YTD.getCode());//7
			record.setProofCount(0.0f);//订单单量为0
			tOrderNewMapper.updateByPrimaryKeySelective(record);
			
			//更新统计表
			updateCount(o.getOrderNo());
			
			//新增奖金信息表数据
			TOrderBonus bonus = new TOrderBonus();
			bonus.setId(UUID.randomUUID().toString());
			bonus.setOrderNo(o.getOrderNo());
			bonus.setGrantBy(TokenManager.getAdminId());                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
			bonus.setGrantTarget(o.getSalesmanId());
			bonus.setBonusSubject(BonusSubject.TK.getCode());//16
			bonusMapper.insertSelective(bonus);
			
			//退单邮件发送需要的数据
			AdminListBo a = adminMapper.getDeptNameByAid(TokenManager.getAdminId());
			
			String content = "<div>退单编号: "+ refund.getId() +"</div><div>客户名称: " + o.getUserName() + "</div>";
			content += "<div>订单编号: "+ o.getOrderNo() +"</div>";
			if(StringUtils.isNotBlank(o.getEmail())){
				
				EmailBo emailBo = new EmailBo("同意退单", o.getEmail(), o.getSalesmanName(), a.getDepartmentName(), a.getName(), content);
				try {
					SendEmailUtil.getInstance().send(emailBo);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				} catch (MessagingException e) {
					e.printStackTrace();
				}
			}
			//发送站内消息
			//addNotic(o.getOrderNo(),NoticeStatus.ORDER_REFUND.getCode(),o.getSalesmanId());//给营销员
			//根据订单编号获得所有的技术员
			List<TOrderTask> l = taskMapper.getReceiverByOid(o.getOrderNo());
			for (TOrderTask tOrderTask : l) {
				if(null != tOrderTask && null != tOrderTask.getTaskReceiver()){
					//addNotic(o.getOrderNo(),NoticeStatus.ORDER_REFUND.getCode(),tOrderTask.getTaskReceiver());//给技术员
					//发邮件给技术员
					if(StringUtils.isNotBlank(tOrderTask.getEmail())){
						EmailBo emailBo = new EmailBo("同意退单", tOrderTask.getEmail(), tOrderTask.getName(), a.getDepartmentName(), a.getName(), content);
						try {
							SendEmailUtil.getInstance().send(emailBo);
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();
						} catch (MessagingException e) {
							e.printStackTrace();
						}
					}
				}
			}
			
		}else{//审核拒绝
			//给营销员发通知和邮件
			TOrderNewBo o = tOrderNewMapper.agreeEmailData(refund.getId());
			//addNotic(o.getOrderNo(),NoticeStatus.ORDER_REFUND_REFUSE.getCode(),o.getSalesmanId());//给营销员
			AdminListBo a = adminMapper.getDeptNameByAid(TokenManager.getAdminId());
			
			String content = "<div>退单编号: "+ refund.getId() +"</div><div>客户名称: " + o.getUserName() + "</div>";
			 content += "<div>订单编号: "+ o.getOrderNo() +"</div>";
			 String email = o.getEmail();
			if(StringUtils.isNotBlank(email)){
				email = email.substring(0, email.indexOf(","));
				String sale = o.getSalesmanName();
				sale = sale.substring(0,sale.indexOf(","));
				if(email.matches("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+")){//email格式校验
					EmailBo emailBo = new EmailBo("拒绝退单",email, sale, a.getDepartmentName(), a.getName(), content);
					try {
						SendEmailUtil.getInstance().send(emailBo);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					} catch (MessagingException e) {
						e.printStackTrace();
					}
				}
			}
		}
		
		//修改退单审核状态
		return refundMapper.updateRefundById(refund);
	}

	@Override
	public Integer addRefundFlow(TOrderBillNew billNew) {
		// 查看收款总金额流水
		
		BigDecimal bd = billNewMapper.getAmountByOid(billNew.getOrderNo());
		billNew.setTransactionAmount(billNew.getTransactionAmount().abs());//绝对值
		int lstaus = 3;
		//如果小于要退的金额 return -1
		//如果等于要退的金额 lstatus 4
		//如果大于 要退的金额 lstatus 3
		if(bd.compareTo(billNew.getTransactionAmount()) == -1){
			return -1;
		}else if(bd.compareTo(billNew.getTransactionAmount()) == 0){
			lstaus = 4;
		}
		
		//新增退款流水
		billNew.setBillNo(UUID.randomUUID().toString().replaceAll("-", ""));
		billNew.setCreater(TokenManager.getAdminId());
		billNew.setTransactionAmount(billNew.getTransactionAmount().negate());// 取负数
		int result = billNewMapper.insertSelective(billNew);
		
		//修改订单数据结算状态和结算金额
		TOrderNew orderNew = new TOrderNew();
		orderNew.setOrderNo(billNew.getOrderNo());
		TOrderNew o = tOrderNewMapper.selectByPrimaryKey(billNew.getOrderNo());
		//这里修改退款金额数据之前退的金额加上本次退的金额
		orderNew.setRefundAmount(billNew.getTransactionAmount().add(o.getRefundAmount()));
		orderNew.setRefundAmount(o.getSettlementAmount().subtract(billNew.getTransactionAmount().abs()));
		orderNew.setLiquidationStatus(lstaus);
		if(lstaus == 4){//如果款项全部退完就更改订单状态,这里不一定待商榷
			addOrderLog(billNew.getOrderNo(), OrderLogProcess.WCTD.getCode(),billNew.getRemarks());
			//orderNew.setProcessStatus(6);
		}
		if(result > 0){
			result = tOrderNewMapper.updateByPrimaryKeySelective(orderNew);
		}
		return result;
	}

	@Override
	public TOrderBillNew selectOneRefundFlow(String BillNo) {
		return billNewMapper.getOneRefundFlow(BillNo);
	}

	@Override
	public List<TOrderBillNew> selectOneOrderAllRefundFlow(String orderNo) {
		return billNewMapper.getOneOrderAllRefundFlow(orderNo);
	}

	@Override
	public Integer updateProofreading(TOrderNew orderNew) {
		// 创建人
		orderNew.setProofAid(TokenManager.getAdminId());
		//校对状态
		orderNew.setProofStatus(1);
		//校对时间
		orderNew.setProofTime(new Date());
		tOrderNewMapper.updateByPrimaryKeySelective(orderNew);
		
		updateCount(orderNew.getOrderNo());
		return 0;
	}
	
	
	private void updateCount(String orderNo){
		//获得订单数据
		TOrderNew new1 = tOrderNewMapper.selectByPrimaryKey(orderNo);
		Calendar cal = Calendar.getInstance();
		cal.setTime(new1.getSignTime());
		int sy = cal.get(Calendar.YEAR);
		int sm = cal.get(Calendar.MONTH);
		Integer month = sy*100+(sm+1);
		
		//重新校对月统计
		int c = monthReportMapper.updateByMonth(month);
		LoggerUtils.debug(logger, "更新订单统计【%s】条。", c);
	}

	@Override
	public int updateContractNo(TOrderNew orderNew) {
		return tOrderNewMapper.updateByPrimaryKeySelective(orderNew);
	}

	@Override
	public int updateFinanceApproval(String orderNo,String remarks) {
		TOrderNew t=new TOrderNew();
		TOrderNew new1 =checkDeleteSign(orderNo);
		if (new1.getProcessStatus()!=3) {
			throw new BusinessException("订单流程不正确。");
		}
		t.setOrderNo(orderNo);
		if (new1.getBackStatus()==3) {
			t.setBackStatus(0);
		}
		List<String> aids = new ArrayList<>();
		if (new1.getApproval()==ApprovalNewState.DSH.getCode()||
				new1.getApproval()==ApprovalNewState.BH.getCode()) {
			t.setProcessStatus(ProcessStatus.YPTPSH.getCode());
			for (Admin admin : adminMapper.getAdminRoleList("总裁")) {
				aids.add(admin.getId());
			}
		}else {
			t.setProcessStatus(ProcessStatus.YPZXSGLY.getCode());
			OrganizationListOut oo=organizationManagementMapper.selectAllById(new1.getOrderDep());
			t.setFinanceId(oo.getFinanceId());
			for (Admin admin : adminMapper.getAdminRoleList("咨询师管理员")) {
				aids.add(admin.getId());
			}
		}
		TOrderLog tl=new TOrderLog();
		tl.setAid(TokenManager.getAdminId());
		tl.setOrderNo(t.getOrderNo());
		tl.setProcess(OrderLogProcess.CWPD.getCode());
		tl.setRemarks(remarks);
		tOrderLogMapper.insertSelective(tl);
		orderNewService.pushGeneralSendNoticeAndEmail(aids, NoticeStatus.ORDER_YES.getCode(),t.getOrderNo(), TokenManager.getAdminId(),new1.getApproval());
		return tOrderNewMapper.updateByPrimaryKeySelective(t);
	}

	

}


