package com.clx.performance.service.impl.breakcontract;

import com.alibaba.fastjson.JSON;
import com.clx.performance.config.BreakContractConfig;
import com.clx.performance.dao.breakcontract.BreakContractDriverRecordDao;
import com.clx.performance.dao.breakcontract.BreakContractOwnerRuleDao;
import com.clx.performance.dao.breakcontract.BreakContractSettlementDriverDao;
import com.clx.performance.dao.breakcontract.BreakContractSettlementDriverDetailDao;
import com.clx.performance.enums.BreakContractSettlementDriverEnum;
import com.clx.performance.enums.BreakContractSettlementLogEnum;
import com.clx.performance.enums.OrderChildLogEnum;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.extranal.document.DocumentService;
import com.clx.performance.model.breakcontract.BreakContractDriverRecord;
import com.clx.performance.model.breakcontract.BreakContractOwnerRule;
import com.clx.performance.model.breakcontract.BreakContractSettlementDriver;
import com.clx.performance.model.breakcontract.BreakContractSettlementDriverDetail;
import com.clx.performance.param.mq.BreakContractDriverRecordAddMqParam;
import com.clx.performance.param.mq.BreakContractOwnerRuleAddMqParam;
import com.clx.performance.service.breakcontract.BreakContractMqHandlerService;
import com.clx.performance.service.breakcontract.BreakContractSettlementLogService;
import com.clx.performance.service.impl.UniqueOrderNumService;
import com.clx.performance.service.payment.PayService;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.utils.LocalDateTimeUtils;
import com.msl.document.api.vo.ContractEvidenceRecordVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
public class BreakContractMqHandlerServiceImpl implements BreakContractMqHandlerService {

    @Autowired
    private BreakContractOwnerRuleDao breakContractOwnerRuleDao;
    @Autowired
    private BreakContractDriverRecordDao breakContractDriverRecordDao;
    @Autowired
    private BreakContractSettlementDriverDetailDao breakContractSettlementDriverDetailDao;
    @Autowired
    private BreakContractSettlementDriverDao breakContractSettlementDriverDao;

    @Autowired
    private DocumentService documentService;

    @Autowired
    private BreakContractConfig breakContractConfig;

    @Autowired
    private BreakContractSettlementLogService breakContractSettlementLogService;
    @Autowired
    private UniqueOrderNumService uniqueOrderNumService;

    @Autowired
    private PayService payService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void ownerRuleAdd(BreakContractOwnerRuleAddMqParam mq) {

        BreakContractOwnerRule rule = breakContractOwnerRuleDao.getEntityByKey(mq.getRuleId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        Map<String,String> map = JSON.parseObject(rule.getRuleJson(), Map.class);

        // 创建合同
        Long contractNo = documentService.createContract(breakContractConfig.getTemplateNo(), map);
        ContractEvidenceRecordVo contract = documentService.getContractInfo(contractNo);

        // 更新违约规则文档
        rule.setFile(contract.getFileUrl());
        breakContractOwnerRuleDao.updateFile(rule);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void driverRecordAdd(BreakContractDriverRecordAddMqParam mq) {
        BreakContractDriverRecord record = breakContractDriverRecordDao.getEntityByKey(mq.getRecordId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        String settlementNo = settlementNoGenerate();

        record.setSettlementNo(settlementNo);

        BreakContractSettlementDriverDetail detail = new BreakContractSettlementDriverDetail();
        detail.setBreakNo(record.getBreakNo());
        detail.setBreakContractPartyType(record.getBreakContractPartyType());
        detail.setSettlementNo(settlementNo);
        detail.setTruckOwnUserNo(record.getTruckOwnUserNo());
        detail.setTruckOwnName(record.getTruckOwnName());
        detail.setDriverUserNo(record.getDriverUserNo());
        detail.setDriverName(record.getDriverName());

        detail.setChildNo(record.getChildNo());
        detail.setFigure(record.getFigure());
        detail.setBreakContractRemark(record.getRemark());

        detail.setCreateBy(record.getCreateBy());
        detail.setCreateName(record.getCreateName());

        BreakContractSettlementDriver settlement = new BreakContractSettlementDriver();
        settlement.setBreakContractPartyType(detail.getBreakContractPartyType());
        settlement.setBreakNo(detail.getBreakNo());
        settlement.setSettlementNo(detail.getSettlementNo());
        settlement.setTruckOwnUserNo(detail.getTruckOwnUserNo());
        settlement.setTruckOwnName(detail.getTruckOwnName());
        settlement.setDriverUserNo(detail.getDriverUserNo());
        settlement.setDriverName(detail.getDriverName());

        settlement.setChildNo(detail.getChildNo());
        settlement.setFigure(detail.getFigure());
        settlement.setBreakContractRemark(detail.getBreakContractRemark());
        settlement.setSettleStatus(BreakContractSettlementDriverEnum.SettleStatus.NO.getCode());
        settlement.setCreateBy(detail.getCreateBy());
        settlement.setCreateName(detail.getCreateName());
        settlement.setSettlePlatform(BreakContractSettlementDriverEnum.SettlePlatform.MSL.getCode());

        breakContractDriverRecordDao.updateSettlementNo(record);

        breakContractSettlementDriverDetailDao.saveEntity(detail);

        breakContractSettlementDriverDao.saveEntity(settlement);

        //保存结算单日志----创建结算单
        breakContractSettlementLogService.saveBreakSettlementLog(settlementNo,
                BreakContractSettlementLogEnum.Type.CREATE_SETTLEMENT.getCode(),BreakContractSettlementLogEnum.Type.CREATE_SETTLEMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),record.getCreateBy(),record.getCreateName());

        try {
            pay(settlement);
        }catch (ServiceSystemException e){
            settlement.setPayRemark(e.getMessage());
            breakContractSettlementDriverDao.updatePayFail(settlement);
        }

    }

    private String settlementNoGenerate() {
        return "WYJSD"+uniqueOrderNumService.getUniqueOrderNum(
                LocalDateTimeUtils.convertLocalDateTimeToString(LocalDateTime.now(), LocalDateTimeUtils.DATE_DAY));
    }

    /**
     * 支付
     */
    private void pay(BreakContractSettlementDriver settlement){

        // 车主
        if (Objects.equals(settlement.getBreakContractPartyType(), BreakContractSettlementDriverEnum.BreakContractPartyType.DRIVER.getCode())){

            payService.driverPay(settlement.getSettlementNo(), settlement.getTruckOwnUserNo(), settlement.getFigure().intValue());
        }
        // 平台
        else if (Objects.equals(settlement.getBreakContractPartyType(), BreakContractSettlementDriverEnum.BreakContractPartyType.PLATFORM.getCode())) {
            payService.payDriver(settlement.getSettlementNo(), settlement.getTruckOwnUserNo(), settlement.getFigure().intValue());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void paySuccess(String settlementNo){
        log.info("违约结算单支付回调, settlementNo:{}", settlementNo);
        BreakContractSettlementDriver breakContractSettlementDriver = breakContractSettlementDriverDao.selectBySettlementNo(settlementNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        if (Objects.equals(breakContractSettlementDriver.getSettleStatus(), BreakContractSettlementDriverEnum.SettleStatus.YES.getCode())){
            log.info("违约结算单支付回调, 结算单已支付, settlementNo:{}", settlementNo);
            return;
        }

        breakContractSettlementDriver.setSettleStatus(BreakContractSettlementDriverEnum.SettleStatus.YES.getCode());
        breakContractSettlementDriver.setSettleTime(LocalDateTime.now());
        breakContractSettlementDriverDao.updateSettlementStatus(breakContractSettlementDriver);

        //保存结算单日志
        breakContractSettlementLogService.saveBreakSettlementLog(settlementNo,
                BreakContractSettlementLogEnum.Type.COMPLETED.getCode(),BreakContractSettlementLogEnum.Type.COMPLETED.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),0L,"系统");
    }

    @Override
    public void payFail(String settlementNo, String remark) {
        log.info("违约结算单支付失败回调, settlementNo:{}, remark:{}", settlementNo, remark);
        BreakContractSettlementDriver breakContractSettlementDriver = breakContractSettlementDriverDao.selectBySettlementNo(settlementNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        if (Objects.equals(breakContractSettlementDriver.getSettleStatus(), BreakContractSettlementDriverEnum.SettleStatus.YES.getCode())){
            log.info("违约结算单支付失败回调, 结算单已支付, settlementNo:{}", settlementNo);
            return;
        }

        breakContractSettlementDriver.setPayRemark(remark);
        breakContractSettlementDriverDao.updatePayFail(breakContractSettlementDriver);

    }

}
