package cn.superdesk.uniorder.service.invoice.impl;

import cn.superdesk.libs.common.json.JsonUtils;
import cn.superdesk.libs.common.util.CollectionUtils;
import cn.superdesk.uniorder.common.ResponseResult;
import cn.superdesk.uniorder.common.enums.ExceptionMsg;
import cn.superdesk.uniorder.common.enums.credit.UnifiedOrderCreditBackStatus;
import cn.superdesk.uniorder.common.enums.credit.UnifiedOrderCreditInvoiceApplyStatus;
import cn.superdesk.uniorder.common.enums.credit.UnifiedOrderCreditInvoiceMakeStatus;
import cn.superdesk.uniorder.common.enums.order.UnifiedOrderAccountingState;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderInvoiceStatus;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderTypeDim;
import cn.superdesk.uniorder.common.exception.SuperdeskUniOrderException;
import cn.superdesk.uniorder.dao.entity.accounting.score.customer.AccountingScoreCustomer;
import cn.superdesk.uniorder.dao.entity.accounting.unified.customer.AccountingUnifiedCustomer;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderCredit;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApply;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApplyExample;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceOrder;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceOrderExample;
import cn.superdesk.uniorder.dao.entity.order.ExpressCompany;
import cn.superdesk.uniorder.dao.entity.sys.SysConfig;
import cn.superdesk.uniorder.dao.mapper.accounting.score.customer.AccountingScoreCustomerMapper;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerMapper;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerMapperEx;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerOrderGoodsMapper;
import cn.superdesk.uniorder.dao.mapper.accounting.unified.customer.AccountingUnifiedCustomerOrderGoodsMapperEx;
import cn.superdesk.uniorder.dao.mapper.base.UnifiedOrderCreditMapper;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.*;
import cn.superdesk.uniorder.dao.mapper.order.ExpressCompanyMapper;
import cn.superdesk.uniorder.dao.mapper.sys.SysConfigMapper;
import cn.superdesk.uniorder.dto.param.invoice.InvoiceApplyOrderGoodsFocusScoreParams;
import cn.superdesk.uniorder.dto.param.invoice.InvoiceApplyOrderGoodsFocusUnifiedParams;
import cn.superdesk.uniorder.dto.param.invoice.InvoiceApplyParams;
import cn.superdesk.uniorder.dto.vo.accounting.unified.customer.ViewDzOrder;
import cn.superdesk.uniorder.dto.vo.invoice.*;
import cn.superdesk.uniorder.dto.vo.invoice.customer.OrderSnMapInvoiceApply;
import cn.superdesk.uniorder.dto.vo.score.ScoreOrderReconciliationNotYetVo;
import cn.superdesk.uniorder.service.invoice.InvoiceApplyService;
import cn.superdesk.uniorder.service.invoice.InvoiceOrderService;
import cn.superdesk.uniorder.service.score.ScoreOrderService;
import cn.superdesk.uniorder.utils.BeanUtils;
import cn.superdesk.uniorder.utils.DateHelper;
import cn.superdesk.uniorder.utils.JwtUtil;
import cn.superdesk.uniorder.utils.LamdaUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class InvoiceApplyCustomerServiceImpl implements InvoiceApplyService {


	@Autowired
	InvoiceApplyMapper          invoiceApplyMapper;
	@Autowired
	InvoiceApplyMapperEx        invoiceApplyMapperEx;
	@Autowired
	InvoiceApplyMapperExScore   invoiceApplyMapperExScore;
	@Autowired
	InvoiceApplyMapperExUnified invoiceApplyMapperExUnified;


	@Autowired
	InvoiceOrderMapper   invoiceOrderMapper;
	@Autowired
	InvoiceOrderMapperEx invoiceOrderMapperEx;
	@Autowired
	InvoiceOrderService  invoiceOrderService;

	@Autowired
	AccountingUnifiedCustomerMapper   accountingUnifiedCustomerMapper;
	@Autowired
	AccountingUnifiedCustomerMapperEx accountingUnifiedCustomerMapperEx;

	@Autowired
	AccountingUnifiedCustomerOrderGoodsMapper   accountingUnifiedCustomerOrderGoodsMapper;
	@Autowired
	AccountingUnifiedCustomerOrderGoodsMapperEx accountingUnifiedCustomerOrderGoodsMapperEx;


	@Autowired
	AccountingScoreCustomerMapper accountingScoreCustomerMapper;

	@Autowired
	ScoreOrderService        scoreOrderService;
	@Autowired
	UnifiedOrderCreditMapper unifiedOrderCreditMapper;

	@Autowired
	SysConfigMapper sysConfigMapper;


	@Autowired
	ExpressCompanyMapper expressCompanyMapper;

	/**
	 * 发票申请 提交 前的 操作
	 *
	 * @param params
	 * @return
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	public List<InvoiceApplySelectScoreVo> invoiceApplySelectFocusUnified(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExUnified.invoiceApplySelectFocusUnified(params);
	}

	/**
	 * 发票申请 提交 前的 操作
	 *
	 * @param params
	 * @return
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	public List<InvoiceApplySelectScoreVo> invoiceApplySelectFocusScore(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExScore.invoiceApplySelectFocusScore(params);
	}


	/**
	 * 发票审核 opt btn 提交
	 *
	 * @param token
	 * @param params
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void invoiceApply(String token, InvoiceApplyParams params) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);


		InvoiceApply invoiceApply = new InvoiceApply();

		Map<String, Object> codeMap = GetConfigByINVA();

		// 生成 发票申请SN
		invoiceApply.setInvoiceNo(codeMap.get("sn").toString());
		// 记录对账单类型 是一般订单的对账单还是积分订单的对账单
		invoiceApply.setAccountingOrderType(params.getAccountingOrderType());

		invoiceApply.setInvoiceTitle(params.getInvoiceTitle());
		invoiceApply.setInvoiceType(params.getInvoiceType());

		invoiceApply.setTaxRate(params.getTaxRate());

		invoiceApply.setFreeAmount(params.getFreeAmount());
		invoiceApply.setRealAmount(params.getRealAmount());
		invoiceApply.setNoCheckCount(params.getNoCheckCount());

		invoiceApply.setRemark(params.getRemark());

		invoiceApply.setApplyUserId(Long.valueOf(userId));
		invoiceApply.setApplyTime(DateHelper.getNow());

		invoiceApplyMapper.insertSelective(invoiceApply);

		List<Long> toDoList = new ArrayList<>();


		switch (AccountingOrderTypeDim.get(params.getAccountingOrderType())) {
			case 一般订单:


				List<InvoiceApplyOrderGoodsFocusUnifiedParams> applyOrderGoodsFocusUnifiedParamsList = params.getApplyOrderGoodsFocusUnifiedParamsList();

				// TODO 如果有多个对账单 最好还是 验证一下 是否同一个企业为好
				for (InvoiceApplyOrderGoodsFocusUnifiedParams invoiceApplyOrderGoodsFocusUnifiedParams : applyOrderGoodsFocusUnifiedParamsList) {

					InvoiceOrder invoiceOrder = new InvoiceOrder();

					// 反正都是 iterator 就写这里了
					toDoList.add(invoiceApplyOrderGoodsFocusUnifiedParams.getAccountingOrderId());

					// 获取刚刚insert的Id
					invoiceOrder.setInvoiceApplyId(invoiceApply.getId());

					invoiceOrder.setAccountingOrderType(AccountingOrderTypeDim.一般订单.getKey());

					// unified_order_goods.id 非传过来的goodsId 是系统自增生成的 Id
					invoiceOrder.setDzGoodId(invoiceApplyOrderGoodsFocusUnifiedParams.getGoodsId());
					// accounting_unified_customer_order.id 中间表的 订单Id
					invoiceOrder.setDzOrderId(invoiceApplyOrderGoodsFocusUnifiedParams.getOrderId());
					// accounting_unified_customer.id
					invoiceOrder.setDzId(invoiceApplyOrderGoodsFocusUnifiedParams.getAccountingOrderId());

					invoiceOrderMapper.insertSelective(invoiceOrder);

				}

				break;

			case 积分订单:

				List<InvoiceApplyOrderGoodsFocusScoreParams> applyOrderGoodsFocusScoreParamsList = params.getApplyOrderGoodsFocusScoreParamsList();

				for (InvoiceApplyOrderGoodsFocusScoreParams invoiceApplyOrderGoodsFocusScoreParams : applyOrderGoodsFocusScoreParamsList) {

					InvoiceOrder invoiceOrder = new InvoiceOrder();

					// 反正都是 iterator 就写这里了
					toDoList.add(invoiceApplyOrderGoodsFocusScoreParams.getAccountingOrderId());

					// 获取刚刚insert的Id
					invoiceOrder.setInvoiceApplyId(invoiceApply.getId());
					invoiceOrder.setAccountingOrderType(AccountingOrderTypeDim.积分订单.getKey());
					invoiceOrder.setUnifiedOrderCreditId(invoiceApplyOrderGoodsFocusScoreParams.getUnifiedOrderCreditId());
					// unified_order_goods.id 非传过来的goodsId 是系统自增生成的 Id
					invoiceOrder.setDzGoodId(invoiceApplyOrderGoodsFocusScoreParams.getUnifiedOrderGoodsId());
					// accounting_unified_customer_order.id 中间表的 订单Id
					invoiceOrder.setDzOrderId(invoiceApplyOrderGoodsFocusScoreParams.getUnifiedOrderId());
					// accounting_unified_customer.id
					invoiceOrder.setDzId(invoiceApplyOrderGoodsFocusScoreParams.getAccountingOrderId());

					invoiceOrderMapper.insertSelective(invoiceOrder);

					// TODO 还要更新 流水的开票 状态
					UnifiedOrderCredit update4InvoiceApplyStatus = new UnifiedOrderCredit();
					update4InvoiceApplyStatus.setId(invoiceApplyOrderGoodsFocusScoreParams.getUnifiedOrderCreditId());
					update4InvoiceApplyStatus.setInvoiceApplyStatus(UnifiedOrderCreditInvoiceApplyStatus.已申请.getKey());
					unifiedOrderCreditMapper.updateByPrimaryKeySelective(update4InvoiceApplyStatus);


				}


				break;
		}


		// TODO 还要更新 发票申请的开票 状态 UnifiedOrderInvoiceState
//					已开票(1, "已开票"),
//					未开票(2, "未开票"),
//					部分开票(3, "部分开票");

		// 这个是对账单状态
		for (Long accountingOrderId : toDoList) {

			/** ----------------------------------------- 更新 对账单 开票状态 ----------------------------------------- **/

			switch (AccountingOrderTypeDim.get(params.getAccountingOrderType())) {
				case 一般订单:

					// 用于查找是 全部开票 还是 部分开票的问题
					Integer invoiceStatus = invoiceApplyMapperExUnified.checkInvoiceStatusByAccountingOrderId(accountingOrderId);

					// 现在 这个是 一般订单的 对账单 结算单
					AccountingUnifiedCustomer accountingUnifiedCustomer = new AccountingUnifiedCustomer();
					accountingUnifiedCustomer.setId(accountingOrderId);
					accountingUnifiedCustomer.setInvoiceStatus(invoiceStatus);
					accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(accountingUnifiedCustomer);

					break;

				case 积分订单:

					AccountingScoreCustomer accountingScoreCustomer = new AccountingScoreCustomer();
					accountingScoreCustomer.setId(accountingOrderId);
					accountingScoreCustomer.setInvoiceStatus(AccountingOrderInvoiceStatus.全部开票.getKey());
					accountingScoreCustomerMapper.updateByPrimaryKeySelective(accountingScoreCustomer);

					break;
			}


			/** ----------------------------------------- 更新 对账单 开票状态 ----------------------------------------- **/
		}


		// 更新账单号
		SysConfig snconfig = new SysConfig();
		snconfig.setCode(codeMap.get("key").toString());
		snconfig.setValueDate(new Date((Long) (codeMap.get("valueDate"))));
		snconfig.setValueInt(Integer.parseInt(codeMap.get("valueInt").toString()));

		sysConfigMapper.updateByPrimaryKeySelective(snconfig);
	}


	/**
	 * *************************************** 发票申请管理 start ****************************************
	 **/
	@Override
	public ResponseResult<List<InvoiceApplyPage>> findViewByPageFocusUnified(Map<String, Object> params, int pageNum, int pageSize) throws SuperdeskUniOrderException {

		PageHelper.startPage(pageNum, pageSize);

		List<InvoiceApplyPage> invoiceApplyPageList = invoiceApplyMapperExUnified.selectByCondition(params);

		PageInfo<InvoiceApplyPage> page = new PageInfo<InvoiceApplyPage>(invoiceApplyPageList);
		PageHelper.clearPage();
		return new ResponseResult<List<InvoiceApplyPage>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), invoiceApplyPageList);
	}

	@Override
	public InvoiceApplyDataVo findViewHeadDataFocusUnified(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExUnified.findViewData(params);
	}

	@Override
	public ResponseResult<List<InvoiceApplyPage>> findViewByPageFocusScore(Map<String, Object> params, int pageNum, int pageSize) throws SuperdeskUniOrderException {

		PageHelper.startPage(pageNum, pageSize);

		List<InvoiceApplyPage> invoiceApplyPageList = invoiceApplyMapperExScore.findViewByPage(params);

		PageInfo<InvoiceApplyPage> page = new PageInfo<InvoiceApplyPage>(invoiceApplyPageList);
		PageHelper.clearPage();
		return new ResponseResult<List<InvoiceApplyPage>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), invoiceApplyPageList);
	}

	@Override
	public InvoiceApplyDataVo findViewHeadDataFocusScore(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExScore.findViewHeadData(params);
	}
	 /****************************************** 发票申请管理   end ******************************************/


	/**
	 * 审核? - 操作 opt 同意?
	 *
	 * @param token
	 * @param params
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void check(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		Long id = Long.valueOf(params.get("id").toString());

//		InvoiceApplyExample searchExample = new InvoiceApplyExample();
//		searchExample.createCriteria()
//				.andAccountingOrderIdEqualTo(id);

		InvoiceApply invoiceApply = invoiceApplyMapper.selectByPrimaryKey(id);

		if (null == invoiceApply) {
			return;
		}

		InvoiceApply invoiceApply4Update = new InvoiceApply();

		invoiceApply4Update.setId(Long.valueOf(params.get("id").toString()));
		invoiceApply4Update.setAuditUserId(Long.valueOf(userId));
		invoiceApply4Update.setAuditTime(DateHelper.getNow());
		invoiceApply4Update.setAuditStatus(Integer.valueOf(params.get("auditStatus").toString()));

		invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply4Update);



		 /****************************************** 连带更新这个发票申请 的 对账单 的 开发票状态 ******************************************/

		// TODO 写死 1-未审核;2-同意;3-拒绝;
		if (params.get("auditStatus").toString().equals("3")) {

			InvoiceOrderExample example = new InvoiceOrderExample();

			example.createCriteria()
					.andInvoiceApplyIdEqualTo(Long.valueOf(params.get("id").toString()));

			List<InvoiceOrder> invoiceOrderList = invoiceOrderMapper.selectByExample(example);


			List<Long> affectedAccountingOrderIds = invoiceOrderList.stream().filter(LamdaUtils.distinctByKey(o -> o.getDzId())).collect(Collectors.toList());


			/**
			 * TODO 妈的，这个是有病吧，只 order_goods 维度 去 更新 对账单 开票 状态 ?
			 * InvoiceOrder 这个表最小是 uog... 不要以为 order
			 * 要过滤出对账单id 呀! kao
			 *
			 * 开票申请编号：IN2020071600003 已经证明不同企业的对账单是可以在同一个发票申请里边的
			 */
//			for (InvoiceOrder invoiceOrder : invoiceOrderList) {
			for(Long accountingOrderId : affectedAccountingOrderIds){

				// 更新 对账单 开票状态
				AccountingUnifiedCustomer accountingUnifiedCustomer = new AccountingUnifiedCustomer();

				Integer status = invoiceApplyMapperExUnified.checkInvoiceStatusByAccountingOrderId(accountingOrderId);

				accountingUnifiedCustomer.setId(accountingOrderId);
				accountingUnifiedCustomer.setInvoiceStatus(status);

				accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(accountingUnifiedCustomer);


			}
		}

		 /****************************************** 连带更新这个发票申请 的 对账单 的 开发票状态 ******************************************/
	}

	@Override
	public List<InvoiceApplyExcel> exportInvoiceApplyExcelFocusUnified(Map<String, Object> params) throws SuperdeskUniOrderException {
		return invoiceApplyMapperExUnified.exportInvoiceApplyExcelFocusUnified(params);
	}

	/**
	 * 前端  客户结算 - 发票申请管理 - 详情
	 *
	 * @param params
	 * @return
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	public InvoiceApplyDetailDimGoodsVo getUnifiedCustomerInvoice2GoodsDetail(Map<String, Object> params) throws SuperdeskUniOrderException {

//		eg:
//		// 发票申请Id
//		params.put("id", getLong("id"));

		Long id = Long.valueOf(params.get("id").toString());

//		InvoiceApplyExample searchExample = new InvoiceApplyExample();
//		searchExample.createCriteria()
//				.andAccountingOrderIdEqualTo(id);

		InvoiceApply invoiceApply = invoiceApplyMapper.selectByPrimaryKey(id);

		if (null == invoiceApply) {
			return null;
		}


		List<InvoiceApplyPage> invoiceApplyPageList = invoiceApplyMapperExUnified.selectByCondition(params);

		InvoiceApplyDetailDimGoodsVo invoiceApplyDetailVo = new InvoiceApplyDetailDimGoodsVo();

		if (CollectionUtils.isNotEmpty(invoiceApplyPageList)) {

			InvoiceApplyPage invoiceApplyPage = invoiceApplyPageList.get(0);

			BeanUtils.copyProperties(invoiceApplyPage, invoiceApplyDetailVo);


			List<ViewDzOrder> dzOrders = null;

			dzOrders = invoiceApplyMapperExUnified.findInvoiceApplyDetailNewDim1Unified2Goods(invoiceApplyDetailVo.getId());

//			switch (AccountingOrderTypeDim.get(invoiceApply.getAccountingOrderType())) {
//				case 一般订单:
//
//					// TODO 坑位 真他妈的 随意
////					List<ViewDzOrder> dzOrders = invoiceApplyMapperEx.findDzOrderByGoodId(invoiceApplyDetailVo.getId());
////
////					// 先去查老的?如果没有再去查新的?
////					if (dzOrders != null && dzOrders.size() > 0) {
////						invoiceApplyDetailVo.setDzOrders(dzOrders);
////					} else {
////						dzOrders = invoiceApplyMapperEx.findDzOrderByGoodIdNew(invoiceApplyDetailVo.getId());
////						invoiceApplyDetailVo.setDzOrders(dzOrders);
////					}
//
//
//
//					break;
//				case 积分订单:
//
//					dzOrders = invoiceApplyMapperEx.findInvoiceApplyDetailDim1Score2Goods(invoiceApplyDetailVo.getId());
//
//					break;
//				default:
//					break;
//			}

			invoiceApplyDetailVo.setDzOrders(dzOrders);


			return invoiceApplyDetailVo;
		}

		return null;
	}

	@Override
	public InvoiceApplyDetailDimCreditVo getUnifiedCustomerInvoice2CreditDetail(Map<String, Object> params) throws SuperdeskUniOrderException {


		//		eg:
//		// 发票申请Id
//		params.put("id", getLong("id"));

		Long id = Long.valueOf(params.get("id").toString());

//		InvoiceApplyExample searchExample = new InvoiceApplyExample();
//		searchExample.createCriteria()
//				.andAccountingOrderIdEqualTo(id);

		InvoiceApply invoiceApply = invoiceApplyMapper.selectByPrimaryKey(id);

		if (null == invoiceApply) {
			return null;
		}

		List<InvoiceApplyPage> invoiceApplyPageList = invoiceApplyMapperExUnified.selectByCondition(params);

		InvoiceApplyDetailDimCreditVo invoiceApplyDetailDimCreditVo = new InvoiceApplyDetailDimCreditVo();

		if (CollectionUtils.isNotEmpty(invoiceApplyPageList)) {

			InvoiceApplyPage invoiceApplyPage = invoiceApplyPageList.get(0);

			BeanUtils.copyProperties(invoiceApplyPage, invoiceApplyDetailDimCreditVo);


			 /****************************************** start ******************************************/


//			/mnt1t/JAVA_HOME/svn2git/superdesk-uniorder/superdesk-uniorder-web/src/main/java/cn/superdesk/uniorder/controller/accounting/customer/ScoreCustomerStatementController.java
			// 240
			// 得到 发票申请 X 积分流水
			// |---- 筛选条件
			List<Long> idsCredit = invoiceOrderService.findCreditSetByInvoicApplyId(id);

			Map<String, Object> setCreditListParams = new HashMap<>();
			setCreditListParams.put("ids", idsCredit.toArray());
			// 客户对账:1-已对账;2-未对账 这个方法默认的是 2
			setCreditListParams.put("accountingStateCustomer", 1);

			log.info("setCreditListParams {}", JsonUtils.toJson(setCreditListParams));

			ResponseResult<List<ScoreOrderReconciliationNotYetVo>> setCreditListObj = new ResponseResult<>();
			setCreditListObj = scoreOrderService.getScoreOrderReconciliationNotYet(setCreditListParams, 0, 1000);

			for (ScoreOrderReconciliationNotYetVo vo : setCreditListObj.getData()) {
				vo.setAccountingStateCustomerName(UnifiedOrderAccountingState.getDesc(vo.getAccountingStateCustomer()));

				vo.setInvoiceApplyStatusName(UnifiedOrderCreditInvoiceApplyStatus.getDesc(vo.getInvoiceApplyStatus()));
				vo.setInvoiceMakeStatusName(UnifiedOrderCreditInvoiceMakeStatus.getDesc(vo.getInvoiceMakeStatus()));
				vo.setBackStatusName(UnifiedOrderCreditBackStatus.getDesc(vo.getBackStatus()));
			}

			 /******************************************   end ******************************************/


			invoiceApplyDetailDimCreditVo.setDzOrders(setCreditListObj.getData());


			return invoiceApplyDetailDimCreditVo;
		}

		return null;
	}


	/**
	 * 操作 - opt 发票登记
	 *
	 * @param token
	 * @param params
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	public void invoiceRegister(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		String invoiceNumber = params.get("invoiceNumber").toString();

		//dz add
		String           dateStr = params.get("datestr").toString();
		SimpleDateFormat sdf     = new SimpleDateFormat("yyyy-MM-dd");


		InvoiceApplyExample example = new InvoiceApplyExample();
		example.createCriteria()
				.andInvoiceNumberEqualTo(invoiceNumber)
				.andMakeInvoiceStatusEqualTo(1);// TODO 写死

		List<InvoiceApply> invoiceApplyList = invoiceApplyMapper.selectByExample(example);

		if (invoiceApplyList != null && invoiceApplyList.size() > 0) {
			throw new SuperdeskUniOrderException(ExceptionMsg.INVOICE_EXIST);
		}


		InvoiceApply invoiceApply = new InvoiceApply();
		invoiceApply.setId(Long.valueOf(params.get("id").toString()));
		invoiceApply.setMakeUserId(Long.valueOf(userId));
		try {
			invoiceApply.setMakeInvoiceTime(sdf.parse(dateStr));
		} catch (ParseException e) {

			e.printStackTrace();
		}
		// TODO 写死
		invoiceApply.setMakeInvoiceStatus(1);
		invoiceApply.setInvoiceNumber(invoiceNumber);
		invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
	}

	/**
	 * 操作 - opt 寄票登记
	 *
	 * @param token
	 * @param sendInvoiceRegisterList
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void sendInvoiceRegister(String token, List<Map> sendInvoiceRegisterList) throws SuperdeskUniOrderException {

		for (Map map : sendInvoiceRegisterList) {

			InvoiceApply invoiceApply = new InvoiceApply();
			// TODO 写死
			invoiceApply.setInvoiceStatus(1);
			invoiceApply.setMailTickTime(DateHelper.getNow());
			invoiceApply.setId(Long.valueOf(map.get("id").toString()));
			invoiceApply.setExpressCompanyId(Long.valueOf(map.get("expressCompanyId").toString()));

			if (map.get("expressNo") != null) {
				invoiceApply.setExpressNo(map.get("expressNo").toString());
			}

			invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
		}
	}

	/**
	 * 客户结算 - 发票管理 - opt 导入发票信息
	 *
	 * @param token
	 * @param list
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void importInvoiceExcel(String token, List<Map<String, Object>> list) throws SuperdeskUniOrderException {

		String userId = JwtUtil.checkToken(token);

		List<InvoiceApply> invoiceApplys = new ArrayList<>();

		boolean flag  = true;
		String  error = "";
		int     h     = 1;

		for (Map<String, Object> map : list) {

			InvoiceApplyExample          example  = new InvoiceApplyExample();
			InvoiceApplyExample.Criteria criteria = example.createCriteria();

			String invoiceNo     = map.get("invoiceNo").toString();
			String invoiceNumber = map.get("invoiceNumber").toString();

			criteria.andInvoiceNoEqualTo(invoiceNo);
			// TODO 写死
			criteria.andAuditStatusEqualTo(2);
			List<InvoiceApply> invoiceApplyList = invoiceApplyMapper.selectByExample(example);

			if (invoiceApplyList != null && invoiceApplyList.size() > 0) {
				InvoiceApply invoiceApply = invoiceApplyList.get(0);
				// TODO 写死
				invoiceApply.setMakeInvoiceStatus(1);
				invoiceApply.setMakeUserId(Long.valueOf(userId));
				invoiceApply.setMakeInvoiceTime(DateHelper.getNow());
				invoiceApply.setInvoiceNumber(invoiceNumber);
				invoiceApplys.add(invoiceApply);
			} else {
				flag = false;
				error += "第" + h + "行," + invoiceNo + ",该发票申请号错误或未审核通过.";
			}

			InvoiceApplyExample          example1  = new InvoiceApplyExample();
			InvoiceApplyExample.Criteria criteria1 = example1.createCriteria();
			criteria1.andInvoiceNumberEqualTo(invoiceNumber);
			// TODO 写死
			criteria1.andMakeInvoiceStatusEqualTo(1);

			List<InvoiceApply> invoiceApplyList1 = invoiceApplyMapper.selectByExample(example1);

			if (invoiceApplyList1 != null && invoiceApplyList1.size() > 0) {
				flag = false;
				error += "第" + h + "行," + invoiceNumber + ",该发票号已存在.";
			}

			h++;
		}

		if (flag) {
			for (InvoiceApply invoiceApply : invoiceApplys) {
				invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
			}
		} else {
			throw new SuperdeskUniOrderException(500, error);
		}
	}

	/**
	 * 客户结算 - 发票管理 - opt 导入寄票信息
	 *
	 * @param token
	 * @param list
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void importSendInvoiceExcel(String token, List<Map<String, Object>> list) throws SuperdeskUniOrderException {

		String             userId        = JwtUtil.checkToken(token);
		List<InvoiceApply> invoiceApplys = new ArrayList<>();
		boolean            flag          = true;
		String             error         = "";
		int                h             = 1;
		for (Map<String, Object> map : list) {
			InvoiceApplyExample          example       = new InvoiceApplyExample();
			InvoiceApplyExample.Criteria criteria      = example.createCriteria();
			String                       invoiceNumber = map.get("invoiceNumber").toString();
			criteria.andInvoiceNumberEqualTo(invoiceNumber);
			// TODO 写死
			criteria.andMakeInvoiceStatusEqualTo(1);
			List<InvoiceApply> invoiceApplyList = invoiceApplyMapper.selectByExample(example);

			if (invoiceApplyList != null && invoiceApplyList.size() > 0) {

				InvoiceApply invoiceApply = invoiceApplyList.get(0);
				// TODO 写死
				invoiceApply.setInvoiceStatus(1);
				invoiceApply.setMakeUserId(Long.valueOf(userId));
				invoiceApply.setMailTickTime(DateHelper.getNow());
				String               expressCompanyName = map.get("expressCompanyName").toString();
				List<ExpressCompany> expressCompanyList = expressCompanyMapper.selectByCompanyName(expressCompanyName);

				if (expressCompanyList != null && expressCompanyList.size() > 0) {
					ExpressCompany expressCompany = expressCompanyList.get(0);
					invoiceApply.setExpressCompanyId(expressCompany.getId());
				} else {
					flag = false;
					error += "第" + h + "行," + expressCompanyName + ",该快递公司名称不正确.";
				}

				if (map.get("expressNo") != null) {
					String expressNo = map.get("expressNo").toString();
					invoiceApply.setExpressNo(expressNo);
				}

				invoiceApplys.add(invoiceApply);
			} else {
				flag = false;
				error += "第" + h + "行," + invoiceNumber + ",该发票号未开票.";
			}
			h++;
		}

		if (flag) {
			for (InvoiceApply invoiceApply : invoiceApplys) {
				invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);
			}
		} else {
			throw new SuperdeskUniOrderException(500, error);
		}
	}

	/**
	 * 操作 - opt 重新开票?
	 *
	 * @param token
	 * @param params
	 * @throws SuperdeskUniOrderException
	 */
	@Override
	@Transactional
	public void invoiceAgain(String token, Map<String, Object> params) throws SuperdeskUniOrderException {

		Long id = Long.valueOf(params.get("id").toString());

		InvoiceApply invoiceApply = invoiceApplyMapper.selectByPrimaryKey(id);

		// TODO 写死
		if (!invoiceApply.getBackAccountStatus().equals(0)) {
			throw new SuperdeskUniOrderException(ExceptionMsg.INVOICE_HAVE_BACK);
		}

		// TODO 写死
		invoiceApply.setAuditStatus(3);
		// TODO 写死
		invoiceApply.setMakeInvoiceStatus(2);
		// TODO 写死
		invoiceApply.setInvoiceStatus(2);
		invoiceApply.setExpressCompanyId(null);
		invoiceApply.setExpressNo(null);
		invoiceApply.setInvoiceNumber(null);

		invoiceApplyMapper.updateByPrimaryKey(invoiceApply);

		InvoiceOrderExample example = new InvoiceOrderExample();
		example
				.createCriteria()
				.andInvoiceApplyIdEqualTo(Long.valueOf(params.get("id").toString()));
		List<InvoiceOrder> ls = invoiceOrderMapper.selectByExample(example);
		for (InvoiceOrder invoiceOrder : ls) {

			AccountingUnifiedCustomer dzMain = new AccountingUnifiedCustomer();

			Integer status = invoiceApplyMapperExUnified.checkInvoiceStatusByAccountingOrderId(invoiceOrder.getDzId());

			dzMain.setId(invoiceOrder.getDzId());
			dzMain.setInvoiceStatus(status);
			accountingUnifiedCustomerMapper.updateByPrimaryKeySelective(dzMain);
		}

	}

	@Override
	public List<ExpressCompany> findExpressCompany() throws SuperdeskUniOrderException {
		return expressCompanyMapper.findAll();
	}

	@Override
	public List<InvoiceApply> findAll(Map<String, Object> params) {
		return invoiceApplyMapperEx.findAll(params);
	}

	@Override
	public InvoiceApply findById(long id) {
		return invoiceApplyMapper.selectByPrimaryKey(id);
	}

	@Override
	public ResponseResult<List<InvoiceApply>> findInvoiceByPageNew(Map<String, Object> params, int pageNo, int pageSize) {
		PageHelper.startPage(pageNo, pageSize);

		List<InvoiceApply> ls = invoiceApplyMapperEx.findAll(params);

		PageInfo<InvoiceApply> page = new PageInfo<InvoiceApply>(ls);
		PageHelper.clearPage();
		return new ResponseResult<List<InvoiceApply>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), ls);
	}

	@Override
//	@Cacheable(keyGenerator = "findByXXKeyGenerator")
	public List<InvoiceApply> findInvoiceByOrderSn(Map<String, Object> invQuery) {

		if (null == invQuery.get("orderSn")) {
			return null;
		}

		return invoiceApplyMapperEx.findInvoiceByOrderSn(invQuery);
	}

	@Override
	public Map<String, InvoiceApply> findInvoiceByOrderSnList(List<String> orderSnList) {

		log.info("findInvoiceByOrderSnList 1 .size {}", orderSnList.size());

		if (CollectionUtils.isEmpty(orderSnList)) {
			return null;
		}

		Map<String, InvoiceApply> result = new HashMap<>();

		Map<String, Object> invQuery = new HashMap<>();
		invQuery.put("orderSnList", orderSnList);
		List<OrderSnMapInvoiceApply> resultList = invoiceApplyMapperEx.findInvoiceByOrderSnList(invQuery);

		log.info("findInvoiceByOrderSnList 2 .size {}", resultList.size());

		try {
			for (OrderSnMapInvoiceApply item : resultList) {


				InvoiceApply temp = new InvoiceApply();

				BeanUtils.copyProperties(item, temp);

				log.info(JsonUtils.toPrettyJson(temp));

				log.info("这个为空的? {}", item.toString());
				log.info("这个为空的? {}", temp.toString());

				result.put(item.getOrderSn(), temp);
			}
		} catch (BeansException e) {
			e.printStackTrace();
		}


		return result;

	}

	private Map<String, Object> GetConfigByINVA() {

		Map<String, Object> map    = new HashMap<>();
		SysConfig           config = sysConfigMapper.selectByPrimaryKey("INVA");
		SimpleDateFormat    sdf    = new SimpleDateFormat("yyyyMMdd");
		Date                dtnow  = new Date();

		if (sdf.format(dtnow).equals(sdf.format(config.getValueDate()))) {
			map.put("valueDate", config.getValueDate().getTime());
			map.put("key", "INVA");
			map.put("valueInt", config.getValueInt() + 1);
			String intStr    = String.valueOf(config.getValueInt() + 1);
			String resintStr = intStr;
			for (int i = intStr.length(); i <= 4; i++) {
				resintStr = "0" + resintStr;
			}
			map.put("sn", config.getValueStr1() + sdf.format(config.getValueDate()) + resintStr);
		} else {
			map.put("valueDate", dtnow.getTime());
			map.put("key", "INVA");
			map.put("valueInt", "1");
			map.put("sn", config.getValueStr1() + sdf.format(dtnow) + "00001");
		}
		return map;
	}

	public static List<Long> arrToListRemoval(String[] arrStr) {
		List<Long> list = new ArrayList<>();
		for (int i = 0; i < arrStr.length; i++) {
			if (!list.contains(arrStr[i])) {
				list.add(Long.valueOf(arrStr[i]));
			}
		}
		return list;
	}
}
