package com.usoft.fin.grpc.bl;

import com.alibaba.fastjson.JSON;
import com.google.protobuf.InvalidProtocolBufferException;
import com.usoft.bizcode.utils.BizCodeUtil;
import com.usoft.fin.grpc.api.entity.*;
import com.usoft.fin.grpc.api.protobuf.*;
import com.usoft.fin.grpc.bl.constants.BusinessType;
import com.usoft.fin.grpc.bl.constants.Status;
import com.usoft.fin.grpc.bl.constants.TableCode;
import com.usoft.fin.grpc.dal.entity.*;
import com.usoft.fin.grpc.dal.entity.CreditApplyUserinfo;
import com.usoft.fin.grpc.dal.entity.vo.CreditApplyVO;
import com.usoft.fin.grpc.dal.entity.vo.CreditVO;
import com.usoft.fin.grpc.dal.mapper.*;
import com.usoft.fin.grpc.entity.PageInfo;
import com.usoft.fin.grpc.utils.*;
import com.usoft.mq.utils.RabbitSendService;
import com.usoft.protobuf.utils.ProtoBufUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 额度 业务领域
 *
 * @author wangdy
 * @date 2018-08-27 10:44
 **/
@Service
public class CreditBl {
	@Autowired
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	private CreditMapper creditMapper;

	@Autowired
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	private CreditApplyMapper creditApplyMapper;

	@Autowired
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	private CreditApplyUserinfoMapper creditApplyUserinfoMapper;

	@Autowired
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	private FileTypeMapper fileTypeMapper;

	@Autowired
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	private CreditApplyUserfileMapper creditApplyUserfileMapper;

	@Autowired
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	private WhiteListMapper whiteListMapper;

	@Autowired
	private MessageBl messageBl;

	@Resource
	private RabbitSendService rabbitSendService;

	/**
	 * 根据code获取额度申请记录
	 *
	 * @param request
	 * @return
	 */
	public GetCreditApplyInfoResponse.Builder getCreditApplyInfo(GetCreditApplyInfoRequest request) throws InvalidProtocolBufferException {
		GetCreditApplyInfoResponse.Builder response = GetCreditApplyInfoResponse.newBuilder();
		// 1.验证参数
		VerifyParamsUtil.hasText(request.getCode(), "额度申请编号不能为空");
		VerifyParamsUtil.isTrue(request.getBusinessType() != 0, "业务类型不能为空");

		// 2.查询额度申请记录
		CreditApplyInfo.Builder ciBuilder = CreditApplyInfo.newBuilder();
		CreditApply creditApply = creditApplyMapper.findByCode(request.getCode());
		if (null == creditApply) {
			throw new FinanceGrpcRuntimeException(-1, "查无此额度申请单");
		}
		// 3.验证增额记录
		if (request.getBusinessType() == BusinessType.ADDCREDIT.getCode()
				&& StringUtils.isBlank(creditApply.getParentCode())) {
			throw new FinanceGrpcRuntimeException(-1, "增额申请有误，未关联额度申请单");
		}
		ciBuilder = ProtoBufUtil.toProtoBuf(ciBuilder, creditApply);

		// 4.获取额度申请的用户信息
		if (request.getBusinessType() == BusinessType.CREDIT.getCode()) {
			List<CreditApplyUserinfo> creditApplyUserinfos = creditApplyUserinfoMapper.findByCreditCode(request.getCode());
			CreditApplyUserinfo creditApplyUserinfo = creditApplyUserinfos.isEmpty() ? null : creditApplyUserinfos.get(0);
			ciBuilder = ciBuilder.setCreditApplyUserinfo(ProtoBufUtil.toProtoBuf(com.usoft.fin.grpc.api.entity.CreditApplyUserinfo.newBuilder(),creditApplyUserinfo));
		}

		// 5.获取所有文件类型 （只存在额度的分类）
		List<FileType> fileTypes = fileTypeMapper.findByProductCodeAndTypeCode(creditApply.getProductCode(), BusinessType.CREDIT.getCode());

		List<CreditApplyUserfile> creditApplyUserfiles = creditApplyUserfileMapper.findByCreditCode(request.getCode());

		// 6.组装数据
		Map<String, List<CreditApplyUserfileInfo>> userfileKV = new HashMap<>(16);
		for (CreditApplyUserfile creditApplyUserfile : creditApplyUserfiles) {
			// 如果没有，则添加
			if(!userfileKV.containsKey(creditApplyUserfile.getFileTypeCode())){
				userfileKV.put(creditApplyUserfile.getFileTypeCode(), new ArrayList<>());
			}
			CreditApplyUserfileInfo.Builder userfileBuilder = CreditApplyUserfileInfo.newBuilder();
			userfileBuilder = ProtoBufUtil.toProtoBuf(userfileBuilder, creditApplyUserfile);

			userfileKV.get(creditApplyUserfile.getFileTypeCode()).add(userfileBuilder.build());
		}

		for (FileType fileType : fileTypes) {
			FileTypeCreditInfo.Builder fileTypeCreditInfo = FileTypeCreditInfo.newBuilder();

			FileTypeInfo.Builder fileTypeInfo = FileTypeInfo.newBuilder();
			fileTypeCreditInfo.setFileTypeInfo(ProtoBufUtil.toProtoBuf(fileTypeInfo, fileType));
			if (userfileKV.containsKey(fileType.getCode())) {
                fileTypeCreditInfo.addAllCreditApplyUserfileInfo(userfileKV.get(fileType.getCode()));
				ciBuilder.addFileTypeCreditInfo(fileTypeCreditInfo);
            }
		}

		response.setCreditApplyInfo(ciBuilder);
		return response;
	}

	/**
	 * 审核额度申请
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public AuditCreditApplyInfoResponse.Builder auditCreditApplyInfo(AuditCreditApplyInfoRequest request) throws InvalidProtocolBufferException {
		// 1.查询该额度申请记录
		CreditApply creditApply = creditApplyMapper.findByCode(request.getCode());
		if (null == creditApply) {
			throw new FinanceGrpcRuntimeException(-1, "不存在该额度申请记录");
		}

		// 2.设置额度申请信息
		creditApply.setEndDate(request.getEndDate());
		creditApply.setRate(BigDecimal.valueOf(request.getRate()));
		creditApply.setStartDate(request.getStartDate());
		creditApply.setStatus((short) request.getStatus());
		creditApply.setReplyAmount(BigDecimal.valueOf(request.getReplyAmount()));
		creditApply.setAuditDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		creditApplyMapper.updateByPrimaryKeySelective(creditApply);

		// 3.生成或覆盖我的额度 （如果审核通过）
		if (request.getStatus() == Status.CREDIT_APPLY_PASS.value()) {
			// 生成一条我的额度主表
			List<Credit> credits = creditMapper.findByEnuuAndProductCode(creditApply.getEnuu(), creditApply.getProductCode());
			Credit credit = new Credit();
			if (!CollectionUtils.isEmpty(credits)) {
				credit = credits.get(0);
			}
			credit.setCreditApplyCode(creditApply.getCode());
			credit.setEndDate(creditApply.getEndDate());
			credit.setRate(creditApply.getRate());
			credit.setReplyAmount(creditApply.getReplyAmount());
			credit.setProductCode(creditApply.getProductCode());
			credit.setEnuu(creditApply.getEnuu());
			credit.setStartDate(creditApply.getStartDate());
			credit.setUsableAmount(creditApply.getReplyAmount());
			credit.setUsedAmount(BigDecimal.valueOf(0));
			if (credit.getId() == null) {
				credit.setCode(BizCodeUtil.genBizCode(TableCode.T_CREDIT.getCode()));
				creditMapper.insertSelective(credit);
			} else {
				creditMapper.updateByPrimaryKeySelective(credit);
			}
		}
		//4.发送额度审核结果站内信消息
		messageBl.auditCreditMessage(request.getCode());
		return AuditCreditApplyInfoResponse.newBuilder();
	}

	/**
	 * 审核增额申请
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public AuditAddCreditApplyInfoResponse.Builder auditAddCreditApplyInfo(AuditAddCreditApplyInfoRequest request) throws InvalidProtocolBufferException {
		// 1.查询该额度申请记录
		CreditApply creditApply = creditApplyMapper.findByCode(request.getCode());
		if (null == creditApply) {
			throw new FinanceGrpcRuntimeException(-1, "不存在该增额申请记录");
		}
		// 2.设置额度申请信息
		creditApply.setEndDate(request.getEndDate());
		creditApply.setRate(BigDecimal.valueOf(request.getRate()));
		creditApply.setStartDate(request.getStartDate());
		creditApply.setStatus((short) request.getStatus());
		creditApply.setReplyAmount(BigDecimal.valueOf(request.getReplyAmount()));
		creditApply.setAuditDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		creditApplyMapper.updateByPrimaryKeySelective(creditApply);

		// 3.生成或覆盖我的额度 （如果审核通过）
		if (request.getStatus() == Status.CREDIT_APPLY_PASS.value()) {
			// 生成一条我的额度主表
			List<Credit> credits = creditMapper.findByEnuuAndProductCode(creditApply.getEnuu(), creditApply.getProductCode());
			Credit credit = new Credit();
			if (!CollectionUtils.isEmpty(credits)) {
				credit = credits.get(0);
			} else {
				throw new FinanceGrpcRuntimeException(-1, "额度信息有误");
			}
			credit.setCreditApplyCode(creditApply.getCode());
			credit.setEndDate(creditApply.getEndDate());
			credit.setRate(creditApply.getRate());
			credit.setReplyAmount(creditApply.getReplyAmount());
			credit.setProductCode(creditApply.getProductCode());
			credit.setEnuu(creditApply.getEnuu());
			credit.setStartDate(creditApply.getStartDate());
			credit.setUsableAmount(BigDecimal.valueOf(request.getUsableAmount()));
			credit.setUsedAmount(BigDecimal.valueOf(request.getUsedAmount()));
			creditMapper.updateByPrimaryKeySelective(credit);
		}
		//4.发送额度消息站内信
		messageBl.auditCreditMessage(request.getCode());
		return AuditAddCreditApplyInfoResponse.newBuilder();
	}

	/**
	 * 保存额度申请用户基础信息
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public SaveCreditApplyUserinfoResponse.Builder saveCreditApplyUserinfo(SaveCreditApplyUserinfoRequest request) {
		SaveCreditApplyUserinfoResponse.Builder response = SaveCreditApplyUserinfoResponse.newBuilder();
		// 1.验证参数
		VerifyParamsUtil.hasText(request.getProductCode(), "产品名称不能为空");

		String resultCreditApplyCode = "";

		List<CreditApply> creditApplies = creditApplyMapper.findByProductCodeAndEnuu(request.getProductCode(), request.getEnuu());
		// 2.没有申请 和 所有申请中没有正在编辑状态都是true，都必须新增
		boolean mustNew = false;
		if (!CollectionUtils.isEmpty(creditApplies)) {
			// 正在编辑的数量
			int countOfEdit = 0;
			CreditApply editCreditApply = null;
			for (CreditApply creditApply : creditApplies) {
				if (creditApply.getStatus() == Status.CREDIT_APPLY_EDIT.value()) {
					countOfEdit ++ ;
					editCreditApply = creditApply;
				}
			}
			if (countOfEdit > 1) {
                throw new FinanceGrpcRuntimeException(-1, "可编辑的额度申请记录大于1，逻辑错误");
            }
            // 3.1 修改存在的记录
			if (countOfEdit == 1) {
				List<CreditApplyUserinfo> creditApplyUserinfos = creditApplyUserinfoMapper.findByCreditCode(editCreditApply.getCode());
				if (CollectionUtils.isEmpty(creditApplyUserinfos) || creditApplyUserinfos.size() > 1) {
					throw new FinanceGrpcRuntimeException(-1, "额度申请记录没有一一对应的用户基础信息");
				}
				BeanUtils.copyProperties(request.getCreditApplyUserinfo() , creditApplyUserinfos.get(0), "code", "creditApplyCode");
				creditApplyUserinfoMapper.updateByPrimaryKeySelective(creditApplyUserinfos.get(0));
				resultCreditApplyCode = creditApplyUserinfos.get(0).getCreditApplyCode();
			} else {
				mustNew = true;
			}
		} else {
			mustNew = true;
		}
		// 3.2 新增用户基础信息
		if (mustNew) {
			CreditApply creditApply = new CreditApply();
			creditApply.setCode(BizCodeUtil.genBizCode(TableCode.T_CREDIT_APPLY.getCode()));
			// 设置编辑中状态
			creditApply.setStatus(Status.CREDIT_APPLY_EDIT.value());
			creditApply.setEnuu(request.getEnuu());
			creditApply.setProductCode(request.getProductCode());

			creditApplyMapper.insertSelective(creditApply);

			CreditApplyUserinfo creditApplyUserinfo = new CreditApplyUserinfo();
			creditApplyUserinfo = JSON.parseObject(
					ProtoBufUtil.toJSONHasTryCatch(request.getCreditApplyUserinfo()), CreditApplyUserinfo.class);

			creditApplyUserinfo.setCreditApplyCode(creditApply.getCode());
			creditApplyUserinfo.setCode(BizCodeUtil.genBizCode(TableCode.T_CREDIT_APPLY_USERINFO.getCode()));
			creditApplyUserinfoMapper.insertSelective(creditApplyUserinfo);
			resultCreditApplyCode = creditApply.getCode();
		}

		response.setCreditApplyCode(resultCreditApplyCode);

		return response;
	}

	/**
	 * 获取额度申请上传资料列表
	 * @param request
	 * @return
	 * @throws InvalidProtocolBufferException
	 */
	public GetCreditApplyUserFilesResponse.Builder getCreditApplyUserFiles(GetCreditApplyUserFilesRequest request) throws InvalidProtocolBufferException {
		CreditApplyInfo.Builder creditApplyInfo = findCreditApplyUserfiles(request.getCreditApplyCode());
		GetCreditApplyUserFilesResponse.Builder response = GetCreditApplyUserFilesResponse.newBuilder();
		ProtoBufUtil.toProtoBuf(response, creditApplyInfo);
		return response;
	}

	/**
	 * 获取额度申请记录的资料信息（包含所有的文件类型）
	 * @param creditApplyCode
	 * @return
	 * @throws InvalidProtocolBufferException
	 */
	private CreditApplyInfo.Builder findCreditApplyUserfiles(String creditApplyCode) throws InvalidProtocolBufferException{
		CreditApplyInfo.Builder ciBuilder = CreditApplyInfo.newBuilder();
		CreditApply creditApply = creditApplyMapper.findByCode(creditApplyCode);
		// 1.获取所有文件类型 （只存在额度的分类）
		List<FileType> fileTypes = fileTypeMapper.findByProductCodeAndTypeCode(creditApply.getProductCode(), BusinessType.CREDIT.getCode());

		List<CreditApplyUserfile> creditApplyUserfiles = creditApplyUserfileMapper.findByCreditCode(creditApplyCode);

		// 2.组装数据
		Map<String, List<CreditApplyUserfileInfo>> userfileKV = new HashMap<>(16);
		for (CreditApplyUserfile creditApplyUserfile : creditApplyUserfiles) {
			if(!userfileKV.containsKey(creditApplyUserfile.getFileTypeCode())){
				userfileKV.put(creditApplyUserfile.getFileTypeCode(), new ArrayList<>());
			}
			CreditApplyUserfileInfo.Builder userfileBuilder = ProtoBufUtil.toProtoBuf(CreditApplyUserfileInfo.newBuilder(), creditApplyUserfile);
			userfileKV.get(creditApplyUserfile.getFileTypeCode()).add(userfileBuilder.build());
		}

		for (FileType fileType : fileTypes) {
			FileTypeCreditInfo.Builder fileTypeCreditInfo = FileTypeCreditInfo.newBuilder();

			FileTypeInfo.Builder fileTypeInfo = FileTypeInfo.newBuilder();
			fileTypeCreditInfo.setFileTypeInfo(ProtoBufUtil.toProtoBuf(fileTypeInfo, fileType));
			if (userfileKV.containsKey(fileType.getCode())) {
				fileTypeCreditInfo.addAllCreditApplyUserfileInfo(userfileKV.get(fileType.getCode()));
			}
			ciBuilder.addFileTypeCreditInfo(fileTypeCreditInfo);
		}
		return ciBuilder;
	}

	/**
	 * 保存额度申请
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public SaveCreditApplyUserFilesResponse.Builder saveCreditApplyUserFiles(SaveCreditApplyUserFilesRequest request) {
		insertCreditApplyUserfile(request.getCreditApplyCode(), request.getSubmitCreditApplyUserfileInfosList());
		return SaveCreditApplyUserFilesResponse.newBuilder();
	}

	/**
	 * 插入额度申请记录资料信息
	 * @param creditApplyCode
	 * @param submitCreditApplyUserfileInfosList
	 */
	private void insertCreditApplyUserfile(String creditApplyCode, List<SubmitCreditApplyUserfileInfos> submitCreditApplyUserfileInfosList) {
		CreditApply creditApply = creditApplyMapper.findByCode(creditApplyCode);
		if (null == creditApply) {
			throw new FinanceGrpcRuntimeException(-1, "申请记录不存在");
		}
		if (creditApply.getStatus() != Status.CREDIT_APPLY_EDIT.value()) {
			throw new FinanceGrpcRuntimeException(-1, "申请记录不在编辑状态");
		}

		// 1.删除存在的资料
		List<CreditApplyUserfile> creditApplyUserfiles = creditApplyUserfileMapper.findByCreditCode(creditApplyCode);
		if (!CollectionUtils.isEmpty(creditApplyUserfiles)) {
			for (CreditApplyUserfile creditApplyUserfile : creditApplyUserfiles) {
				creditApplyUserfileMapper.deleteByPrimaryKey(creditApplyUserfile.getId());
			}
		}

		// 2.保存资料
		for (SubmitCreditApplyUserfileInfos submitCreditApplyUserfileInfos : submitCreditApplyUserfileInfosList) {
			for (CreditApplyUserfileInfo creditApplyUserfileInfo : submitCreditApplyUserfileInfos.getCreditApplyUserfileInfoList()) {
				CreditApplyUserfile creditApplyUserfile = new CreditApplyUserfile();
				creditApplyUserfile.setCode(BizCodeUtil.genBizCode(TableCode.T_CREDIT_APPLY_USERFILE.getCode()));
				creditApplyUserfile.setFileTypeCode(submitCreditApplyUserfileInfos.getCode());
				creditApplyUserfile.setCreditApplyCode(creditApplyCode);
				creditApplyUserfile.setNumber((short) creditApplyUserfileInfo.getNumber());
				creditApplyUserfile.setUrl(creditApplyUserfileInfo.getUrl());
				creditApplyUserfile.setName(creditApplyUserfileInfo.getName());
				creditApplyUserfile.setSize((long) creditApplyUserfileInfo.getSize());
				creditApplyUserfileMapper.insert(creditApplyUserfile);
			}
		}
	}

	/**
	 * 提交额度审核
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public SubmitCreditApplyResponse.Builder submitCreditApply(SubmitCreditApplyRequest request) {
		// 1.保存额度申请记录
		insertCreditApplyUserfile(request.getCreditApplyCode(), request.getSubmitCreditApplyUserfileInfosList());

		// 2.修改额度申请记录状态
		CreditApply creditApply = creditApplyMapper.findByCode(request.getCreditApplyCode());
		creditApply.setStatus(Status.CREDIT_APPLY_WAITTING.value());
		creditApply.setSubmitDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		creditApplyMapper.updateByPrimaryKeySelective(creditApply);

		// 3.添加企业用户白名单
		List<WhiteList> whiteLists = whiteListMapper.findByEnuu(request.getEnuu());
		if (!CollectionUtils.isEmpty(whiteLists) && whiteLists.get(0).getUseruu().intValue() != request.getUseruu()) {
			throw new FinanceGrpcRuntimeException(-1, "您不是白名单成员，无法提交额度申请");
		} else {
			WhiteList whiteList = new WhiteList();
			whiteList.setEnuu(request.getEnuu());
			whiteList.setUseruu(request.getUseruu());
			whiteListMapper.insert(whiteList);
		}
		// TODO 发送腾讯云消息给ERP
		rabbitSendService.sendMessage("finance_10046945","10046945", "1001", String.valueOf(BusinessType.CREDIT.getCode()), creditApply.getCode());

		return SubmitCreditApplyResponse.newBuilder();
	}

	/**
	 * 保存增额申请
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public SaveAddCreditApplyUserFilesResponse.Builder saveAddCreditApplyUserFiles(SaveAddCreditApplyUserFilesRequest request) {
		insertCreditApplyUserfile(request.getAddCreditApplyCode(), request.getSubmitCreditApplyUserfileInfosList());
		return SaveAddCreditApplyUserFilesResponse.newBuilder();
	}

	/**
	 * 提交增额审核
	 * @param request
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public SubmitAddCreditApplyUserFilesResponse.Builder submitAddCreditApply(SubmitAddCreditApplyUserFilesRequest request) {

		// 1.验证增额提交合法性
		CreditApply addCredit = creditApplyMapper.findByCode(request.getAddCreditApplyCode());
		if (null == addCredit) {
			throw new FinanceGrpcRuntimeException(-1, "不存在该增额申请记录");
		}
		List<CreditApply> addCreditApplys = creditApplyMapper.findByParentCode(addCredit.getParentCode());
		if (!CollectionUtils.isEmpty(addCreditApplys)) {
			for (CreditApply addCreditApply : addCreditApplys) {
				if (addCreditApply.getStatus() == Status.CREDIT_APPLY_WAITTING.value()) {
					throw new FinanceGrpcRuntimeException(-1, "当前存在正在申请增额的记录，请等待上条记录申请完成");
				}
			}
		}

		// 2.保存额度申请记录
		insertCreditApplyUserfile(request.getAddCreditApplyCode(), request.getSubmitCreditApplyUserfileInfosList());

		// 3.修改增额申请记录状态
		CreditApply creditApply = creditApplyMapper.findByCode(request.getAddCreditApplyCode());
		creditApply.setStatus(Status.CREDIT_APPLY_WAITTING.value());
		creditApply.setSubmitDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		creditApplyMapper.updateByPrimaryKeySelective(creditApply);

		// 4.发送消息给ERP
		rabbitSendService.sendMessage("finance_10046945","10046945", "1001", String.valueOf(BusinessType.ADDCREDIT.getCode()), creditApply.getCode());

		return SubmitAddCreditApplyUserFilesResponse.newBuilder();
	}


	/**
	 * 验证额度申请
	 * @param request
	 * @return
	 * @throws InvalidProtocolBufferException
	 */
	@Transactional(rollbackFor = Exception.class)
	public CheckCreditApplyInfoResponse.Builder checkCreditApplyInfo(CheckCreditApplyInfoRequest request) throws InvalidProtocolBufferException {
		CheckCreditApplyInfoResponse.Builder response = CheckCreditApplyInfoResponse.newBuilder();
		// 1.验证参数
		VerifyParamsUtil.hasText(request.getProductCode(), "产品名称不能为空");

		List<CreditApply> creditApplies = creditApplyMapper.findByProductCodeAndEnuu(request.getProductCode(), request.getEnuu());

		List<Credit> credits = creditMapper.findByEnuuAndProductCode(request.getEnuu(), request.getProductCode());

		// 2.检验额度申请合法性
		if (!CollectionUtils.isEmpty(credits) && credits.size() ==1) {
			// 判断当前额度是否失效
			if (DateUtils.compareNow(credits.get(0).getStartDate(), credits.get(0).getEndDate())) {
				throw new FinanceGrpcRuntimeException(11, "已存在生效中的额度信息");
			}
		}

		String editCreditApply = "";
		for (CreditApply creditApply : creditApplies) {
			if(creditApply.getStatus() == Status.CREDIT_APPLY_WAITTING.value()) {
				throw new FinanceGrpcRuntimeException(10,"已存在正在审核中的额度信息");
			} else if (creditApply.getStatus() == Status.CREDIT_APPLY_EDIT.value()) {
				editCreditApply = creditApply.getCode();
			}
		}

		// 3.存在正在编辑的就带出用户基础信息
		if (!StringUtils.isBlank(editCreditApply)) {
			List<CreditApplyUserinfo> creditApplyUserinfos = creditApplyUserinfoMapper.findByCreditCode(editCreditApply);
			if (CollectionUtils.isEmpty(creditApplyUserinfos) || creditApplyUserinfos.size() > 1) {
				throw new FinanceGrpcRuntimeException(-1, "额度申请记录没有一一对应的用户基础信息");
			}
			com.usoft.fin.grpc.api.entity.CreditApplyUserinfo.Builder creditApplyUserinfo = ProtoBufUtil.toProtoBuf(com.usoft.fin.grpc.api.entity.CreditApplyUserinfo.newBuilder(), creditApplyUserinfos.get(0));
			response.setCreditApplyUserinfo(creditApplyUserinfo);
		}
		return response;
	}

	/**
	 * 验证增额申请
	 * @param request
	 * @return
	 * @throws InvalidProtocolBufferException
	 */
	@Transactional(rollbackFor = Exception.class)
	public CheckAddCreditApplyInfoResponse.Builder checkAddCreditApplyInfo(CheckAddCreditApplyInfoRequest request) throws InvalidProtocolBufferException {
		CheckAddCreditApplyInfoResponse.Builder response = CheckAddCreditApplyInfoResponse.newBuilder();
		// 1.参数校验
		VerifyParamsUtil.hasText(request.getCreditCode(), "父额度申请不能为空");

		// 2.查询我的当前额度 的额度申请记录信息（找出父额度）
		CreditApply creditApply = creditApplyMapper.findByCode(request.getCreditCode());
		if (!StringUtils.isBlank(creditApply.getParentCode())) {
		    creditApply = creditApplyMapper.findByCode(creditApply.getParentCode());
        }
        VerifyParamsUtil.notNull(creditApply, "不存在该父额度申请记录");
		VerifyParamsUtil.isTrue(!(creditApply.getStatus() == Status.CREDIT_APPLY_EDIT.value()||
				creditApply.getStatus() == Status.CREDIT_APPLY_WAITTING.value() ||
				creditApply.getStatus() == Status.CREDIT_APPLY_UNPASS.value()), "父额度申请非通过状态");

		// 3.查询我的当前额度
		List<Credit> credits = creditMapper.findByCreditApplyCode(request.getCreditCode());
		if (CollectionUtils.isEmpty(credits) || credits.size() > 1) {
			throw new FinanceGrpcRuntimeException(-1, "我的额度信息与额度申请记录对应关系有误");
		}

		// 4.判断当前额度是否失效
		if (!DateUtils.compareNow(credits.get(0).getStartDate(), credits.get(0).getEndDate())) {
			throw new FinanceGrpcRuntimeException(-1, "当前额度已失效，无法增额");
		}

 		// 5.取出父额度下的增额申请草稿
		List<CreditApply> addCreditApplys = creditApplyMapper.findByParentCode(creditApply.getCode());
		CreditApply resultCreditApply = null;
		if (!CollectionUtils.isEmpty(addCreditApplys)) {
            for (CreditApply addCreditApply : addCreditApplys) {
            	if (addCreditApply.getStatus() == Status.CREDIT_APPLY_WAITTING.value()) {
            		throw new FinanceGrpcRuntimeException(-1, "当前存在正在申请增额的记录，请等待上条记录申请完成");
				}
                if (addCreditApply.getStatus() == Status.CREDIT_APPLY_EDIT.value()) {
                    resultCreditApply = addCreditApply;
                }
            }
		}

		// 6.没有则生成草稿
		if (null == resultCreditApply) {
            resultCreditApply = new CreditApply();
            resultCreditApply.setCode(BizCodeUtil.genBizCode(TableCode.T_CREDIT_APPLY.getCode()));
            resultCreditApply.setParentCode(creditApply.getCode());
            resultCreditApply.setStatus(Status.CREDIT_APPLY_EDIT.value());
            resultCreditApply.setEnuu(creditApply.getEnuu());
            resultCreditApply.setProductCode(creditApply.getProductCode());
            creditApplyMapper.insertSelective(resultCreditApply);
        }

		// 7.查询父额度数据
		CreditApplyInfo.Builder creditApplyInfo = findCreditApplyUserfiles(resultCreditApply.getParentCode());
		List<FileTypeCreditInfo> result = new ArrayList<>();
		for (FileTypeCreditInfo fileTypeCreditInfo : creditApplyInfo.getFileTypeCreditInfoList()) {
			if (!CollectionUtils.isEmpty(fileTypeCreditInfo.getCreditApplyUserfileInfoList())) {
				result.add(fileTypeCreditInfo);
			}
		}
		response.addAllFileTypeCreditInfo(result);

		// 8.查询增额数据
		CreditApplyInfo.Builder addCreditApplyInfo = findCreditApplyUserfiles(resultCreditApply.getCode());
		List<FileTypeCreditInfo> addResult = new ArrayList<>();
		Map<String, FileTypeCreditInfo> resultMap = new HashMap<>(result.size());
		for (FileTypeCreditInfo fileTypeCreditInfo : result) {
			resultMap.put(fileTypeCreditInfo.getFileTypeInfo().getCode(), fileTypeCreditInfo);
		}
		for (FileTypeCreditInfo.Builder fileTypeCreditInfo : addCreditApplyInfo.getFileTypeCreditInfoBuilderList()) {
			if (!resultMap.containsKey(fileTypeCreditInfo.getFileTypeInfo().getCode())) {
			    // 增额时非其他类型都要必填
			    if (!fileTypeCreditInfo.getFileTypeInfo().getName().equals("其他")) {
			        fileTypeCreditInfo.setFileTypeInfo(fileTypeCreditInfo.getFileTypeInfoBuilder().setRequired(1));
                }
				addResult.add(fileTypeCreditInfo.build());
			}
		}
		response.setAddCreditCode(resultCreditApply.getCode());
		response.addAllFileTypeAddCreditInfo(addResult);

		return response;

	}

	/**
	 * 获取我的额度列表
	 * @param request
	 * @return
	 * @throws InvalidProtocolBufferException
	 */
	public GetMyCreditInfosResponse.Builder getMyCreditInfos (GetMyCreditInfosRequest request) throws InvalidProtocolBufferException {

		// 1.获取当前企业下的额度信息
		List<CreditVO> creditVOS = creditMapper.findCreditVOByEnuu(request.getEnuu());
		GetMyCreditInfosResponse.Builder response = GetMyCreditInfosResponse.newBuilder();
		for (Credit credit : creditVOS) {
			CreditInfo.Builder cbuilder = ProtoBufUtil.toProtoBuf(CreditInfo.newBuilder(), credit);
			// 2.判断当前额度是否失效
			if (DateUtils.compareNow(credit.getStartDate(), credit.getEndDate())) {
				cbuilder.setStatus(true);
			} else {
				cbuilder.setStatus(false);
			}
			response.addCreditInfo(cbuilder);
		}
		return response;
	}

	/**
	 * 获取我的剩余可用额度（暂时只获取 应收宝）// TODO 暂时只统计保理
	 * @param request
	 * @return
	 */
	public GetMyUsableCreditInfosResponse.Builder getMyUsableCreditInfos (GetMyUsableCreditInfosRequest request) {
		GetMyUsableCreditInfosResponse.Builder response = GetMyUsableCreditInfosResponse.newBuilder();

		List<Credit> credits = creditMapper.findByEnuu(request.getEnuu());
		// 1.暂时只统计保理
		UsableCreditInfo.Builder builder = UsableCreditInfo.newBuilder();
		// 保理
		builder.setCreditType(1);
		if (!CollectionUtils.isEmpty(credits)) {
			builder.setUsableAmount(credits.get(0).getUsableAmount().doubleValue());
		}
		response.addUsableCreditInfo(builder);
		return response;
	}

	/**
	 * 分页获取额度申请列表
	 * @param request
	 * @return
	 * @throws InvalidProtocolBufferException
	 */
	public GetCreditApplyPagingInfoResponse.Builder getCreditApplyPagingInfo (GetCreditApplyPagingInfoRequest request) throws InvalidProtocolBufferException {
		// 1.获取分页数据
		int number = request.getPageNumber();
		int size = request.getPageSize();
		int count = creditApplyMapper.countByEnuu(request.getEnuu());
		PageInfo pageInfo = new PageInfo(number, size, count);
		List<CreditApplyVO> creditApplyVOList = creditApplyMapper.findCreditApplyVOByEnuuAndPage(request.getEnuu(), pageInfo.getStartIndex(), size);

		// 2.返回数据处理
		GetCreditApplyPagingInfoResponse.Builder response = GetCreditApplyPagingInfoResponse.newBuilder();
		PagingInfo.Builder page = PagingInfo.newBuilder();
		ProtoBufUtil.toProtoBuf(page, pageInfo);
		response.setPagingInfo(page);
		for (CreditApplyVO creditApplyVO : creditApplyVOList) {
			CreditApplySimpleInfo.Builder cmBuilder = CreditApplySimpleInfo.newBuilder();
			cmBuilder = ProtoBufUtil.toProtoBuf(cmBuilder, creditApplyVO);
			if (!StringUtils.isBlank(creditApplyVO.getCreditCode())) {
				Credit credit = creditMapper.findByCode(creditApplyVO.getCreditCode());
				if (DateUtils.compareNow(credit.getStartDate(), credit.getEndDate())) {
					cmBuilder.setIsUsed(1);
				} else {
					cmBuilder.setIsUsed(0);
				}
			} else {
				cmBuilder.setIsUsed(0);
			}
			response.addCreditApplySimpleInfo(cmBuilder);
		}

		return response;
	}

	/**
	 * 验证白名单
	 * @param request
	 * @return
	 */
	public CheckWhiteListResponse.Builder checkWhiteList (CheckWhiteListRequest request) {
		CheckWhiteListResponse.Builder response = CheckWhiteListResponse.newBuilder();

		VerifyParamsUtil.hasText(String.valueOf(request.getUseruu()), "用户uu为空");

		List<WhiteList> whiteLists = whiteListMapper.findByEnuu(request.getEnuu());

		// 1.企业没有白名单 与 存在白名单用户的 可以登录
		if (!CollectionUtils.isEmpty(whiteLists)) {
			for (WhiteList whiteList: whiteLists) {
				if (whiteList.getUseruu() == request.getUseruu()) {
					response.setIsWhite(true);
					return response;
				}
			}
		} else {
			response.setIsWhite(true);
			return response;
		}

		response.setIsWhite(false);
		return response;
	}
}
