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

import cn.superdesk.uniorder.common.exception.constants.ExceptionMsg;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerBackAccountStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.InvoiceBankStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerItemBackStatusEnum;
import cn.superdesk.uniorder.common.exception.UnifiedOrderRuntimeException;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.dao.entity.accounting.unified.customer.AccountingUnifiedCustomerOrderGoods;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApply;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApplyXGoods;
import cn.superdesk.uniorder.dao.entity.invoice.customer.InvoiceApplyXGoodsExample;
import cn.superdesk.uniorder.dao.entity.invoice.customer.fundrestream.InvoiceBankStatement;
import cn.superdesk.uniorder.dao.entity.invoice.customer.fundrestream.InvoiceBankStatementExample;
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.invoice.customer.InvoiceApplyMapper;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.InvoiceApplyMapperEx;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.InvoiceApplyXGoodsMapper;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.InvoiceApplyXGoodsMapperEx;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.fundrestream.InvoiceBankStatementMapper;
import cn.superdesk.uniorder.dao.mapper.invoice.customer.fundrestream.InvoiceBankStatementMapperEx;
import cn.superdesk.uniorder.dto.param.invoice.common.InvoiceBankCriteria;
import cn.superdesk.uniorder.dto.vo.unified.UnifiedInvOrderCount;
import cn.superdesk.uniorder.service.invoice.customer.fundrestream.InvoiceBankStatementService;
import cn.superdesk.uniorder.common.numerical.AnBeanUtils;
import cn.superdesk.uniorder.common.numerical.AnDateHelper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @Description: 重构
 * @Author: linjinyu
 * @CreateDate: 2021/7/23 下午2:23
 * @UpdateUser: linjinyu
 * @UpdateDate: 2021/7/23 下午2:23
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Service
public class InvoiceBankStatementServiceImpl implements InvoiceBankStatementService {

	@Autowired
	private InvoiceApplyXGoodsMapper     invoiceApplyXGoodsMapper;
	@Autowired
	private InvoiceApplyXGoodsMapperEx   invoiceApplyXGoodsMapperEx;
	@Autowired
	private InvoiceApplyMapper           invoiceApplyMapper;
	@Autowired
	private InvoiceApplyMapperEx         invoiceApplyMapperEx;
	@Autowired
	private InvoiceBankStatementMapper   invoiceBankStatementMapper;
	@Autowired
	private InvoiceBankStatementMapperEx invoiceBankStatementMapperEx;

	@Autowired
	private AccountingUnifiedCustomerOrderGoodsMapper   accountingUnifiedCustomerOrderGoodsMapper;
	@Autowired
	private AccountingUnifiedCustomerOrderGoodsMapperEx accountingUnifiedCustomerOrderGoodsMapperEx;


	/****************************************** extends BaseService 部分 start ******************************************/
	@Override
	public void addObj(InvoiceBankStatement entity) {
		invoiceBankStatementMapper.insert(entity);
	}

	@Override
	public void updateObj(InvoiceBankStatement entity) {
		invoiceBankStatementMapper.updateByPrimaryKeySelective(entity);
	}

	@Override
	public void deleteObj(Long id) {
	}

	@Override
	public InvoiceBankStatement findById(Long id) {
		return invoiceBankStatementMapper.selectByPrimaryKey(id);
	}


	@Override
	public PageInfo<InvoiceBankStatement> findByPaging(Map<String, Object> conditions, Integer pageNun, Integer pageSize) {
		return null;
	}

	@Override
	public List<InvoiceBankStatement> findAll(Map<String, Object> queryMap) {
		return invoiceBankStatementMapperEx.findAll(queryMap);
	}

	/****************************************** extends BaseService 部分   end ******************************************/


	public void addInvoiceBankStatement(InvoiceBankStatement entity) {
		invoiceBankStatementMapper.insertSelective(entity);
	}

	public void updateInvoiceBankStatement(InvoiceBankStatement entity) {
		InvoiceBankStatement originEntity = invoiceBankStatementMapper.selectByPrimaryKey(entity.getId());
//		AssertUtil.notNull(originEntity);
		AnBeanUtils.copy(entity, originEntity);
		invoiceBankStatementMapper.updateByPrimaryKey(originEntity);
	}

	public void deleteInvoiceBankStatement(Long id) {
		invoiceBankStatementMapper.deleteByPrimaryKey(id);
	}

	public InvoiceBankStatement findInvoiceBankStatementById(Long id) {
		InvoiceBankStatement entity = invoiceBankStatementMapper.selectByPrimaryKey(id);
//		AssertUtil.notNull(entity);
		return entity;
	}

	public R<List<InvoiceBankStatement>> pageQuery(Map<String, Object> conditions, int pageNun, int pageSize) {

		// 样例 保留
//		InvoiceBankStatement invoiceBankStatementConditions = BeanUtils.mapToBean(conditions,InvoiceBankStatement.class);

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

		PageHelper.startPage(pageNun, pageSize);
		List<InvoiceBankStatement>     resultList = invoiceBankStatementMapper.selectByExample(example);
		PageInfo<InvoiceBankStatement> page       = new PageInfo<InvoiceBankStatement>(resultList);
		PageHelper.clearPage();

		return new R<List<InvoiceBankStatement>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), resultList);

	}

	/****************************************** 原来就有 start ******************************************/

	@Override
	public R<List<InvoiceBankStatement>> findViewByPage(InvoiceBankCriteria fromVO, int pageNum, int pageSize) throws UnifiedOrderRuntimeException {

		PageHelper.startPage(pageNum, pageSize);

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

		if (fromVO.getId() != null) {
			criteria.andIdEqualTo(fromVO.getId());
		}

		if (StringUtils.isNotEmpty(fromVO.getBankName())) {
			criteria.andBankNameLike("%" + fromVO.getBankName() + "%");
		}

		if (fromVO.getStatus() != null) {
			criteria.andStatusEqualTo(fromVO.getStatus());
		}

		if (StringUtils.isNotEmpty(fromVO.getPayee())) {
			criteria.andPayeeLike("%" + fromVO.getPayee() + "%");
		}

		if (StringUtils.isNotEmpty(fromVO.getPayeeAccount())) {
			criteria.andPayeeAccountLike("%" + fromVO.getPayeeAccount() + "%");
		}

//        if(fromVO.setPayStartTime())
		if (StringUtils.isNotEmpty(fromVO.getPayStartTime()) && StringUtils.isNotEmpty(fromVO.getPayEndTime())) {
			criteria.andPayTimeBetween(AnDateHelper.parseToDate(fromVO.getPayStartTime()), AnDateHelper.parseToDate(fromVO.getPayStartTime()));
		}

		// TODO 写死
		criteria.andEnableEqualTo(1);

		List<InvoiceBankStatement> ls = invoiceBankStatementMapper.selectByExample(example);

		PageInfo<InvoiceBankStatement> page = new PageInfo<InvoiceBankStatement>(ls);
		PageHelper.clearPage();

		return new R<List<InvoiceBankStatement>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), ls);
	}

	@Override
	@Transactional
	public void importBankStatementExcel(String token, List<InvoiceBankStatement> list) throws UnifiedOrderRuntimeException {

		for (InvoiceBankStatement invoiceBank : list) {

//			InvoiceBank invoiceBank = new InvoiceBank();
//			invoiceBank.setBankName(map.get("bankName").toString());
//			invoiceBank.setRemark(map.get("remark").toString());
//			invoiceBank.setPayeeAccount(map.get("payeeAccount").toString());
//			invoiceBank.setPayee(map.get("payee").toString());
//			invoiceBank.setCount(new BigDecimal(map.get("count").toString()));
//			invoiceBank.setNoCheckCount(new BigDecimal(map.get("count").toString()));
//			invoiceBank.setPayTime(AnDateHelper.parseToDate(map.get("payTime").toString()));
//			invoiceBank.setCreateTime(AnDateHelper.getNow());
//			invoiceBank.setMainName(map.get("mainName").toString());

			invoiceBankStatementMapper.insertSelective(invoiceBank);
		}

	}

	/**
	 * @param params
	 * @throws UnifiedOrderRuntimeException
	 */
	@Override
	public void delete(Map<String, Object> params) throws UnifiedOrderRuntimeException {

		Object id = params.get("id");
		if (id == null) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.ID_NOT_EMPTY);
		}

		InvoiceBankStatement invoiceBank = invoiceBankStatementMapper.selectByPrimaryKey(Long.valueOf(id.toString()));

		if (!invoiceBank.getStatus().equals(0)) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.WATER_CHECK);
		}

		// TODO 写死
		invoiceBank.setEnable(0);

		invoiceBankStatementMapper.updateByPrimaryKeySelective(invoiceBank);
	}

	@Override
	@Transactional
	public void backRegister(Map<String, Object> params) throws UnifiedOrderRuntimeException {

		Date now = AnDateHelper.getNow();

		// 判断商品Id
		String id             = params.get("id").toString();
		String orderGoodIdStr = params.get("orderGoodIds").toString();
		String bankId         = params.get("bankId").toString();

		if (org.apache.commons.lang.StringUtils.isBlank(orderGoodIdStr)) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.GOODIDS_NOT_EMPTY);
		}

		String[] orderGoodIds = orderGoodIdStr.split(",");
		if (orderGoodIds == null || orderGoodIds.length == 0) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.GOODIDS_NOT_EMPTY);
		}

		List<Long> orderGoodIdList = arrToListRemoval(orderGoodIds);

		BigDecimal total = new BigDecimal("0");

		for (String orderGoodId : orderGoodIds) {

			Long goodId = Long.valueOf(orderGoodId);

			AccountingUnifiedCustomerOrderGoods dzOrderGood = accountingUnifiedCustomerOrderGoodsMapper.selectByPrimaryKey(goodId);
			total = total.add(dzOrderGood.getPrice());
		}

		InvoiceBankStatement invoiceBankStatement = invoiceBankStatementMapper.selectByPrimaryKey(Long.valueOf(bankId));
		if (invoiceBankStatement == null) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.GOODIDS_NOT_EMPTY);
		}

		if (total.compareTo(invoiceBankStatement.getNoCheckCount()) == 1) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.WATER_LESS_COUNT);
		}

		InvoiceApply invoiceApply = invoiceApplyMapper.selectByPrimaryKey(Long.valueOf(id));

		// 获取该申请的所以商品配置
		InvoiceApplyXGoodsExample          example  = new InvoiceApplyXGoodsExample();
		InvoiceApplyXGoodsExample.Criteria criteria = example.createCriteria();
		criteria.andInvoiceApplyIdEqualTo(Long.valueOf(id));
		List<InvoiceApplyXGoods> invoiceOrders = invoiceApplyXGoodsMapper.selectByExample(example);

		boolean backAccountStatus = true;

		// 改变 对账单X商品 表 回款状态
		for (InvoiceApplyXGoods invoiceOrder : invoiceOrders) {

			if (orderGoodIdList.contains(invoiceOrder.getUnifiedOrderGoodsId())) {

				invoiceOrder.setBackStatus(InvoiceApplyCustomerItemBackStatusEnum.已回款.getKey());
				invoiceOrder.setBankId(Long.valueOf(bankId));
				invoiceOrder.setBackTime(now);

				invoiceApplyXGoodsMapper.updateByPrimaryKeySelective(invoiceOrder);

			} else {
				// 因为不是选择全部商品,所以是部分回款
				backAccountStatus = false;
			}
		}

		// 判断是全部回款还是部分回款
		if (backAccountStatus) {
			invoiceApply.setBackAccountStatus(InvoiceApplyCustomerBackAccountStatusEnum.已回款.getKey());
		} else {
			invoiceApply.setBackAccountStatus(InvoiceApplyCustomerBackAccountStatusEnum.部分回款.getKey());
		}

		invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);

		// 修改 银行流水 未核销 金额
		BigDecimal noCheckCount = invoiceBankStatement.getNoCheckCount().subtract(total);
		invoiceBankStatement.setNoCheckCount(noCheckCount);

		if (noCheckCount.compareTo(new BigDecimal("5")) == -1) {
			invoiceBankStatement.setStatus(InvoiceBankStatusEnum.全部核销.getKey());
		} else {
			invoiceBankStatement.setStatus(InvoiceBankStatusEnum.部分核销.getKey());
		}

		invoiceBankStatementMapper.updateByPrimaryKeySelective(invoiceBankStatement);
	}

	@Override
	public List<InvoiceBankStatement> getBankByApplyId(Map<String, Object> params) throws UnifiedOrderRuntimeException {
		return invoiceBankStatementMapperEx.getBankByApplyId(params);
	}

	/**
	 * opt 删除-回款登记
	 *
	 * @param params
	 * @throws UnifiedOrderRuntimeException
	 */
	@Override
	@Transactional
	public void deleteBackRegister(Map<String, Object> params) throws UnifiedOrderRuntimeException {

		String invoiceBankIdsStr  = params.get("bankId").toString();
		String invoiceApplyIdsStr = params.get("invoiceApplyId").toString();

		if (org.apache.commons.lang.StringUtils.isBlank(invoiceBankIdsStr)) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.GOODIDS_NOT_EMPTY);
		}

		String[] bankIds = invoiceBankIdsStr.split(",");

		if (bankIds == null || bankIds.length == 0) {
			throw new UnifiedOrderRuntimeException(ExceptionMsg.GOODIDS_NOT_EMPTY);
		}

		List<Long> bankIdList = arrToListRemoval(bankIds);

		InvoiceApply invoiceApply = new InvoiceApply();
		invoiceApply.setId(Long.valueOf(invoiceApplyIdsStr));
		invoiceApply.setBackAccountStatus(InvoiceApplyCustomerBackAccountStatusEnum.未回款.getKey());
		invoiceApplyMapper.updateByPrimaryKeySelective(invoiceApply);

		for (Long bankId : bankIdList) {

			InvoiceApplyXGoodsExample example = new InvoiceApplyXGoodsExample();

			example.createCriteria()
					.andInvoiceApplyIdEqualTo(Long.valueOf(invoiceApplyIdsStr))
					.andBankIdEqualTo(bankId);

			List<InvoiceApplyXGoods> invoiceOrders = invoiceApplyXGoodsMapper.selectByExample(example);

			for (InvoiceApplyXGoods invoiceOrder : invoiceOrders) {

				invoiceOrder.setBackTime(null);
				invoiceOrder.setBankId(null);
				invoiceOrder.setBackStatus(InvoiceApplyCustomerItemBackStatusEnum.未回款.getKey());

				invoiceApplyXGoodsMapper.updateByPrimaryKeySelective(invoiceOrder);

			}

			InvoiceBankStatement invoiceBank = invoiceBankStatementMapper.selectByPrimaryKey(bankId);
			invoiceBank.setNoCheckCount(invoiceBank.getCount());
			invoiceBank.setStatus(InvoiceBankStatusEnum.未核销.getKey());
			invoiceBankStatementMapper.updateByPrimaryKeySelective(invoiceBank);
		}
	}

	@Override
	public List<UnifiedInvOrderCount> getInvOrderCount(Long id) {
		return invoiceBankStatementMapperEx.getInvOrderCount(id);
	}


	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;
	}
}
