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.Status;
import com.usoft.fin.grpc.bl.constants.TableCode;
import com.usoft.fin.grpc.dal.entity.*;
import com.usoft.fin.grpc.dal.entity.vo.RepayVO;
import com.usoft.fin.grpc.dal.mapper.*;
import com.usoft.fin.grpc.entity.PageInfo;
import com.usoft.fin.grpc.utils.FinanceGrpcRuntimeException;
import com.usoft.fin.grpc.utils.VerifyParamsUtil;
import com.usoft.protobuf.utils.ProtoBufUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

/**
 * 还款Bl
 * @author wangmh
 * @date 2018-08-23 15:04
 **/
@Service
public class RepayBl {

    /**
     * 一天的毫秒数
     */
    private static final long TIMESTAMP_ONE_DAY = 1000 * 60 * 60 * 24;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private CreditMapper creditMapper;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private RepayPlanMapper repayPlanMapper;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private RepayMapper repayMapper;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private RepayDetailMapper repayDetailMapper;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private DrawApplyMapper drawApplyMapper;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private MessageBl messageBl;

    @Autowired
    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private ProductMapper productMapper;

    @Transactional(rollbackFor = Exception.class)
    public RepayDrawInfoResponse.Builder repayDrawInfo(RepayDrawInfoRequest request) throws InvalidProtocolBufferException {
        RepayDrawInfoResponse.Builder response = RepayDrawInfoResponse.newBuilder();
        String drawApplyCode = request.getDrawApplyCode();
        VerifyParamsUtil.hasText(drawApplyCode, "提款编号不能为空");

        // 获取提款申请记录
        DrawApply drawApply = drawApplyMapper.findByCode(drawApplyCode);
        if (drawApply == null) {
            throw new FinanceGrpcRuntimeException("找不到提款编号对应的提款申请记录");
        }

        // 更新额度表
        String creditCode = drawApply.getCreditCode();
        Credit credit = new Credit();
        credit.setCode(creditCode);
        // 设置已用额度
        credit.setUsedAmount(BigDecimal.valueOf(request.getCreditUsedAmount()));
        // 设置剩余额度
        credit.setUsableAmount(BigDecimal.valueOf(request.getCreditUsableAmount()));
        creditMapper.updateByCodeSelective(credit);

        // 获取用户还款信息
        Repay repay = repayMapper.findByDrawCode(drawApplyCode);
        if (repay == null) {
            throw new FinanceGrpcRuntimeException("找不到提款编号对应的用户还款信息");
        }

        // 保存还款记录列表
        List<RepayDetail> repayDetails = new ArrayList<>();
        List<RepayDetailInfo> repayDetailInfos = request.getRepayDetailInfoList();
        for (RepayDetailInfo repayDetailInfo : repayDetailInfos) {
            RepayDetail repayDetail = JSON.parseObject(ProtoBufUtil.toJSONHasTryCatch(repayDetailInfo), RepayDetail.class);
            repayDetail.setCode(BizCodeUtil.genBizCode(TableCode.T_REPAY_DETAIL.getCode()));
            repayDetail.setRepayCode(repay.getCode());
            // TODO 加不加这个看数据库改不改
            repayDetail.setShouldRepayTotal(BigDecimal.valueOf(repayDetailInfo.getActualRepayTotal()));
            repayDetails.add(repayDetail);
        }
        repayDetailMapper.deleteAllByRepayCode(repay.getCode());
        repayDetailMapper.insertAllSelective(repayDetails);

        // 最新的还款
        RepayPlan newPlanInfo = null;

        // 保存还款计划列表
        List<RepayPlan> repayPlans = new ArrayList<>();
        List<RepayPlanInfo> repayPlanInfos = request.getRepayPlanInfoList();
        for (RepayPlanInfo repayPlanInfo : repayPlanInfos) {
            RepayPlan repayPlan = JSON.parseObject(ProtoBufUtil.toJSONHasTryCatch(repayPlanInfo), RepayPlan.class);
            repayPlan.setCode(BizCodeUtil.genBizCode(TableCode.T_REPAY_PLAN.getCode()));
            repayPlan.setRepayCode(repay.getCode());
            repayPlans.add(repayPlan);
            if (repayPlan.getStatus() == Status.REPAY_NOT_PAY.value()) {
                newPlanInfo = newPlanInfo == null ? repayPlan : newPlanInfo.getPeriodsNumber() < repayPlan.getPeriodsNumber() ? newPlanInfo : repayPlan;
            }
        }
        // 假如全部还清，则取期数最大的还款计划
        if (null == newPlanInfo) {
            repayPlans.sort(Comparator.comparing(RepayPlan::getPeriodsNumber));
            newPlanInfo = repayPlans.get(repayPlans.size() - 1);
        }
        repayPlanMapper.deleteAllByRepayCode(repay.getCode());
        repayPlanMapper.insertAllSelective(repayPlans);

        // 更新还款表
        repay.setRepayPlanCode(newPlanInfo.getCode());
        repay.setCurrentRepayMoment(newPlanInfo.getShouldRepayTotal());
        repay.setCurrentRepayTime(newPlanInfo.getRepayDate());
        repayMapper.updateByPrimaryKeySelective(repay);

        response.setResponseHeader(ResponseHeader.newBuilder());
        //发送还款消息
        messageBl.repayDrawMessage(repay.getCode());
        return response;
    }

    /**
     * 获取还款计划
     * @param request
     * @return
     * @throws InvalidProtocolBufferException
     */
    public GetRepayPlanInfoResponse.Builder getRepayPlanInfo(GetRepayPlanInfoRequest request) throws InvalidProtocolBufferException {
        GetRepayPlanInfoResponse.Builder response = GetRepayPlanInfoResponse.newBuilder();
        VerifyParamsUtil.hasText(request.getDrawApplyCode(), "提款申请编号不能为空");
        DrawApply drawApply = drawApplyMapper.findByCode(request.getDrawApplyCode());
        VerifyParamsUtil.notNull(drawApply, "未查到提款信息");
        List<RepayPlan> repayPlans = repayPlanMapper.findByDrawCode(request.getDrawApplyCode());
        VerifyParamsUtil.notNull(repayPlans, "未查到还款计划");
        response.setDrawApplyInfo(ProtoBufUtil.toProtoBuf(DrawApplyInfo.newBuilder(), JSON.toJSONString(drawApply)));
        for (RepayPlan repayPlan : repayPlans) {
            response.addRepayPlanInfo(ProtoBufUtil.toProtoBuf(RepayPlanInfo.newBuilder(), JSON.toJSONString(repayPlan)));
        }
        // 获取产品信息
        Product product = productMapper.findByCode(drawApply.getProductCode());
        VerifyParamsUtil.notNull(product, "未查到当前产品");
        response.setProductInfo(ProtoBufUtil.toProtoBuf(ProductInfo.newBuilder(), product));
        return response;
    }

    /**
     * 获取我的传款分页信息
     * @param request
     * @return
     * @throws InvalidProtocolBufferException
     */
    public GetMyRepayPagingInfoResponse.Builder getMyRepayPagingInfo(GetMyRepayPagingInfoRequest request) throws InvalidProtocolBufferException {
        GetMyRepayPagingInfoResponse.Builder response = GetMyRepayPagingInfoResponse.newBuilder();
        int enuu = request.getEnuu();
        int number = request.getPageNumber();
        int size = request.getPageSize();
        int count = repayMapper.countByEnuu(enuu);
        PageInfo pageInfo = new PageInfo(number, size, count);
        List<RepayVO> repayVOList =  repayMapper.selectListByEnuu(pageInfo.getStartIndex(), size, enuu);
        response.setPagingInfo(ProtoBufUtil.toProtoBuf(PagingInfo.newBuilder(), pageInfo));
        for (Repay repay : repayVOList) {
            RepayInfo.Builder rBuilder = RepayInfo.newBuilder();
            // 计算剩余时间
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            long nowDate = System.currentTimeMillis();
            try {
                Date should = df.parse(repay.getCurrentRepayTime());
                long day = (should.getTime() - nowDate) / (TIMESTAMP_ONE_DAY);
                rBuilder.setRestDate(Math.toIntExact(day));
                response.addRepayInfo(ProtoBufUtil.toProtoBuf(rBuilder, repay));
            } catch (ParseException e) {
                throw new FinanceGrpcRuntimeException("还款记录数据有误");
            }
        }
        return response;
    }

    /**
     * 获取还款明细
     * @param request
     * @return
     * @throws InvalidProtocolBufferException
     */
    public GetRepayDetailResponse.Builder getRepayDetail(GetRepayDetailRequest request) throws InvalidProtocolBufferException {
        GetRepayDetailResponse.Builder response = GetRepayDetailResponse.newBuilder();
        String repayCode = request.getRepayCode();
        VerifyParamsUtil.hasText(repayCode, "还款编号不能为空");
        // 还款计划列表
        List<RepayPlan> repayPlans = repayPlanMapper.findByRepayCode(repayCode);
        for (RepayPlan repayPlan : repayPlans) {
            response.addRepayPlanInfo(ProtoBufUtil.toProtoBuf(RepayPlanInfo.newBuilder(), JSON.toJSONString(repayPlan)));
        }

        // 还款记录列表
        List<RepayDetail> repayDetails = repayDetailMapper.findByRepayCode(repayCode);
        for (RepayDetail repayDetail : repayDetails) {
            response.addRepayDetailInfo(ProtoBufUtil.toProtoBuf(RepayDetailInfo.newBuilder(), JSON.toJSONString(repayDetail)));
        }

        // 提款信息drawCode
        Repay repay = repayMapper.findByCode(repayCode);
        DrawApply drawApply = drawApplyMapper.findByCode(repay.getDrawCode());
        response.setDrawApplyInfo(ProtoBufUtil.toProtoBuf(DrawApplyInfo.newBuilder(), JSON.toJSONString(drawApply)));

        // 获取产品信息
        Product product = productMapper.findByCode(drawApply.getProductCode());
        VerifyParamsUtil.notNull(product, "未查到当前产品");
        response.setProductInfo(ProtoBufUtil.toProtoBuf(ProductInfo.newBuilder(), product));
        return response;
    }
}
