package com.liquidnet.service.bank.currencycloud.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.ResponseDto;
import com.liquidnet.service.adam.incrementer.CustomIdGenerator;
import com.liquidnet.service.bank.currencycloud.constant.BankCcPushConstants;
import com.liquidnet.service.bank.currencycloud.dto.*;
import com.liquidnet.service.bank.currencycloud.entity.BankCcPayment;
import com.liquidnet.service.bank.currencycloud.entity.BankCcPushLog;
import com.liquidnet.service.bank.currencycloud.entity.BankCcTransaction;
import com.liquidnet.service.bank.currencycloud.service.IBankCcPushLogService;
import com.liquidnet.service.bank.currencycloud.service.IBankCcPushNotifyService;
import com.liquidnet.service.bank.currencycloud.service.IBankCcTransactionService;
import com.liquidnet.service.bank.feign.IBankFeignAdamTransactionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.ParseException;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lightnet
 * @since 2020-09-08
 */
@Service("bankCcPushNotifyService")
@Slf4j
public class BankCcPushNotifyServiceImpl implements IBankCcPushNotifyService {

    @Autowired
    CustomIdGenerator customIdGenerator;

    @Autowired
    IBankCcTransactionService bankCcTransactionService;

    @Autowired
    IBankCcPushLogService bankCcPushLogService;

    @Autowired
    IBankFeignAdamTransactionService bankFeignAdamTransactionService;

    @Override
    public ResponseDto pushNotify(BankCcPushNotifyParam param) throws ParseException {
        ResponseDto responseDto = ResponseDto.success();
        // 持久化到数据库
        BankCcPushNotifyHeader header = param.getHeader();
        String messageType = header.getMessageType();
        String notificationType = header.getNotificationType();
        String bodyId = null;
        String body = null;
        ObjectMapper mapper = new ObjectMapper();
        if (BankCcPushConstants.HeaderMessageTypeEnum.cash_manager_transaction.name().equals(messageType)) {
            BankCcPushNotifyFunding funding = mapper.convertValue(param.getBody(), BankCcPushNotifyFunding.class);
            body = JsonUtils.toJson(funding);
            bodyId = funding.getId();
            responseDto = this.pushNotifyFunding(funding);
        } else if (BankCcPushConstants.HeaderMessageTypeEnum.conversion.name().equals(messageType)) {
            BankCcPushNotifyConversion conversion = mapper.convertValue(param.getBody(), BankCcPushNotifyConversion.class);
            body = JsonUtils.toJson(conversion);
            bodyId = conversion.getId();
            responseDto = this.pushNotifyConversion(conversion);
        } else if (BankCcPushConstants.HeaderMessageTypeEnum.payment.name().equals(messageType)) {
            BankCcPushNotifyPayment payment = mapper.convertValue(param.getBody(), BankCcPushNotifyPayment.class);
            body = JsonUtils.toJson(payment);
            bodyId = payment.getId();
            responseDto = this.pushNotifyPayment(payment);
        }
        // 异步持久化推送通知
        BankCcPushLog log = new BankCcPushLog();
        log.setId(String.valueOf(customIdGenerator.nextId(log)));
        log.setMessageType(messageType);
        log.setNotificationType(notificationType);
        log.setBody(body);
        log.setBodyId(bodyId);
        bankCcPushLogService.asyncInsert(log);
        return responseDto;
    }

    private ResponseDto pushNotifyPayment(BankCcPushNotifyPayment param) throws ParseException {
        String dateFormat = "yyyy-MM-dd HH:mm:ssX";

        BankCcPayment dto = new BankCcPayment();
        dto.setId(param.getId());
        dto.setAmount(param.getAmount());
        dto.setBeneficiaryId(param.getBeneficiaryId());
        dto.setCurrency(param.getCurrency());
        dto.setReference(param.getReference());
        dto.setReason(param.getReason());
        dto.setStatus(param.getStatus());
        dto.setCreatorContactId(param.getCreatorContactId());
        dto.setPaymentType(param.getPaymentType());
        dto.setPaymentDate(DateUtil.parse(param.getPaymentDate(), dateFormat));
        dto.setTransferredAt(DateUtil.parse(param.getTransferredAt(), dateFormat));
        dto.setAuthorisationStepsRequired(param.getAuthorisationStepsRequired());
        dto.setLastUpdaterContactId(param.getLastUpdaterContactId());
        dto.setShortReference(param.getShortReference());
        dto.setConversionId(param.getConversionId());
        dto.setFailureReason(param.getFailureReason());
//        dto.setPayerId("");
//        dto.setPayerDetailsSource("");
//        dto.setCreatedAt(new Date());
//        dto.setUpdatedAt(new Date());
        dto.setPaymentGroupId(param.getPaymentGroupId());
        dto.setUniqueRequestId(param.getUniqueRequestId());
        dto.setFailureReturnedAmount(param.getFailureReturnedAmount());
//        dto.setUltimateBeneficiaryName("");
//        dto.setPurposeCode("");
//        dto.setChargeType("");
//        dto.setFeeAmount("");
//        dto.setFeeCurrency("");

        ResponseDto responseDto = bankFeignAdamTransactionService.pushNotifyBankCcPayment(dto);
        return responseDto;
    }

    private ResponseDto pushNotifyFunding(BankCcPushNotifyFunding param) throws ParseException {
        BankCcTransaction bankCcTransaction = new BankCcTransaction();
        bankCcTransaction.setId(param.getId());
        bankCcTransaction.setBalanceId(param.getBalanceId());
        bankCcTransaction.setAccountId(param.getAccountId());
        bankCcTransaction.setCurrency(param.getCurrency());
        bankCcTransaction.setAmount(StringUtils.isEmpty(param.getAmount()) ? BigDecimal.ZERO : new BigDecimal(param.getAmount()));
        bankCcTransaction.setBalanceAmount(StringUtils.isEmpty(param.getBalanceAmount()) ? BigDecimal.ZERO : new BigDecimal(param.getAmount()));
        bankCcTransaction.setType(param.getType());
        bankCcTransaction.setAction(param.getAction());
        bankCcTransaction.setRelatedEntityType(param.getRelatedEntityType());
        bankCcTransaction.setRelatedEntityId(param.getRelatedEntityId());
        bankCcTransaction.setRelatedEntityShortReference(param.getRelatedEntityShortReference());
        bankCcTransaction.setStatus(param.getStatus());
        bankCcTransaction.setReason(param.getReason());

        String dateFormat = "yyyy-MM-dd'T'HH:mm:ssX";

        bankCcTransaction.setSettlesAt(DateUtil.parse(param.getSettlesAt(), dateFormat));
        bankCcTransaction.setCreatedAt(DateUtil.parse(param.getCreatedAt(), dateFormat));
        bankCcTransaction.setUpdatedAt(DateUtil.parse(param.getUpdatedAt(), dateFormat));
        bankCcTransaction.setCompletedAt(DateUtil.parse(param.getCompletedAt(), dateFormat));
        bankCcTransactionService.insertOrUpdate(bankCcTransaction);

        ResponseDto responseDto = bankFeignAdamTransactionService.pushNotifyBankCcFunding(bankCcTransaction);
        return responseDto;
    }

    private ResponseDto pushNotifyConversion(BankCcPushNotifyConversion param) throws ParseException {

        String dateFormat = "yyyy-MM-dd'T'HH:mm:ssX";
        BankCcConversionDto dto = new BankCcConversionDto();
        dto.setId(param.getId());
        dto.setAccountId(param.getAccountId());
        dto.setCreatorContactId(param.getCreatorContactId());
        dto.setShortReference(param.getShortReference());
        dto.setSettlementDate(DateUtil.parse(param.getSettlementDate(), dateFormat));
        dto.setConversionDate(DateUtil.parse(param.getConversionDate(), dateFormat));
        dto.setStatus(param.getStatus());
        dto.setPartnerStatus(param.getPartnerStatus());
        dto.setCurrencyPair(param.getCurrencyPair());
        dto.setBuyCurrency(param.getBuyCurrency());
        dto.setSellCurrency(param.getSellCurrency());
        dto.setFixedSide(param.getFixedSide());
        dto.setPartnerBuyAmount(StringUtils.isEmpty(param.getPartnerBuyAmount()) ? null : new BigDecimal(param.getPartnerBuyAmount()));
        dto.setPartnerSellAmount(StringUtils.isEmpty(param.getPartnerSellAmount()) ? null : new BigDecimal(param.getPartnerSellAmount()));
        dto.setClientBuyAmount(StringUtils.isEmpty(param.getClientBuyAmount()) ? null : new BigDecimal(param.getClientBuyAmount()));
        dto.setClientSellAmount(StringUtils.isEmpty(param.getClientSellAmount()) ? null : new BigDecimal(param.getClientSellAmount()));
        dto.setMidMarketRate(StringUtils.isEmpty(param.getMidMarketRate()) ? null : new BigDecimal(param.getMidMarketRate()));
        dto.setCoreRate(StringUtils.isEmpty(param.getCoreRate()) ? null : new BigDecimal(param.getCoreRate()));
        dto.setPartnerRate(StringUtils.isEmpty(param.getPartnerRate()) ? null : new BigDecimal(param.getPartnerRate()));
        dto.setClientRate(StringUtils.isEmpty(param.getClientRate()) ? null : new BigDecimal(param.getClientRate()));
        dto.setDepositRequired(param.getDepositRequired());
        dto.setDepositAmount(StringUtils.isEmpty(param.getDepositAmount()) ? null : new BigDecimal(param.getDepositAmount()));
        dto.setDepositCurrency(param.getDepositCurrency());
        dto.setDepositStatus(param.getDepositStatus());
        dto.setDepositRequiredAt(DateUtil.parse(param.getDepositRequiredAt(), dateFormat));
//        dto.setUnallocatedFunds(new BigDecimal("0"));
//        dto.setPaymentIdList(Lists.newArrayList());
        dto.setPaymentIds(param.getPaymentIds());
//        dto.setUniqueRequestId("");
//        dto.setCreatedAt(new Date());
//        dto.setUpdatedAt(new Date());
//        dto.setFailureReason("");

        ResponseDto responseDto = bankFeignAdamTransactionService.pushNotifyBankCcConversion(dto);
        return responseDto;
    }

}
