package com.crm.pay.service.impl.pay;

import com.alibaba.fastjson.JSON;
import com.crm.pay.entity.callback.SafeCallbackEntity;
import com.crm.pay.entity.property.SafePayPropertyEntity;
import com.crm.pay.service.FinanceDepositService;
import com.crm.pay.service.SafeService;
import com.crm.pay.service.impl.base.BasePayServiceImpl;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.model.constant.PayConstants;
import com.crm.rely.backend.model.entity.finance.deposit.FinanceDepositAddEntity;
import com.crm.pay.entity.FinanceDepositCallbackUpdateEntity;
import com.crm.rely.backend.model.pojo.table.FinanceDepositTable;
import com.crm.rely.backend.model.pojo.table.SysRemittanceChannelTable;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.util.MD5Util;
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.math.BigDecimal;

/**
 * @description:
 * @author: houn
 * @create: 2020-05-05 23:45
 */
@Slf4j
@Service
public class SafeServiceImpl extends BasePayServiceImpl implements SafeService {

    @Autowired
    private FinanceDepositService balanceService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String pay(FinanceDepositAddEntity balanceSaveEntity) throws Exception {

        //通道配置
        SysRemittanceChannelTable channel = getPayChannel(balanceSaveEntity.getPayType());
        //通道配置实体
        SafePayPropertyEntity payProperty = getPayProperty(channel, SafePayPropertyEntity.class);

        balanceSaveEntity.setCurrency(channel.getCurrency());
        balanceSaveEntity.setTransformCurrency(channel.getTransformCurrency());

        FinanceDepositTable financeDepositTable = balanceService.save(balanceSaveEntity, channel);

        String url = getUrl(financeDepositTable, payProperty);
        //将url加入实体保存
        financeDepositTable.setFormUrl(url);
        
        return url;
    }

    /**
     * 回调处理数据
     *
     * @param callbackEntity 回调实体
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void callback(SafeCallbackEntity callbackEntity) throws Exception {
        log.info(String.format("callback orderNo:%s,callback data:%s", callbackEntity.getOrderNo(), JSON.toJSONString(callbackEntity)));

        boolean flag = validate(callbackEntity);
        if (!flag) {
            throw new ServiceException("fail");
        }

        FinanceDepositCallbackUpdateEntity balanceCallbackUpdateEntity = getFinanceDepositCallbackUpdateEntity(PayConstants.SAFE_SUCCESS, callbackEntity.getOrderNo(), callbackEntity.getTransactionId(), callbackEntity.getStatus(),callbackEntity);

//        if (!Strings.isNullOrEmpty(callbackEntity.getOrderAmount())) {
//            balanceCallbackUpdateEntity.setAmount(new BigDecimal(callbackEntity.getOrderAmount()));
//        }
//        if (!Strings.isNullOrEmpty(callbackEntity.getOrderPayment())) {
//            balanceCallbackUpdateEntity.setTransformAmount(new BigDecimal(callbackEntity.getOrderPayment()));
//        }
//        if (!Strings.isNullOrEmpty(callbackEntity.getOrderAmount()) && !Strings.isNullOrEmpty(callbackEntity.getOrderPayment())) {
//            balanceCallbackUpdateEntity.setRate(balanceCallbackUpdateEntity.getTransformAmount().divide(balanceCallbackUpdateEntity.getAmount()));
//        }
        /**
         * 更新数据
         */
        balanceService.updateCallback(balanceCallbackUpdateEntity);
    }

    /**
     * 获取支付url
     *
     * @param depositTable
     * @return
     * @throws ServiceException
     */
    private String getUrl(FinanceDepositTable depositTable, SafePayPropertyEntity propertyEntity) throws Exception {

        String sign = getSign(propertyEntity, depositTable);

        BigDecimal amount = getAmount(depositTable);

        String url = String.format("%s?orderNo=%s&customerId=%d&orderCurrency=%s&orderAmount=%.0f.00&receiveUrl=%s&pickupUrl=%s&shopNo=%s&signType=%s&sign=%s",
                propertyEntity.getBaseUrl(),
                depositTable.getSerial() + "_" + depositTable.getLogin(),
                depositTable.getCustomId(),
                propertyEntity.getCurrency(),
                amount,
                propertyEntity.getReceiveUrl(),
                propertyEntity.getPickupUrl(),
                propertyEntity.getShopNo(),
                propertyEntity.getSignType(), sign);

        log.info(String.format("支付请求,请求orderNo:%s,请求url:%s", depositTable.getSerial(), url));
        return url;
    }

    /**
     * 验证回调参数是否被篡改
     *
     * @param callbackEntity 回调实体
     * @return
     * @throws ServiceException
     */
    private boolean validate(SafeCallbackEntity callbackEntity) throws Exception {
        SafePayPropertyEntity safePayProperty = getPayProperty(PayConstants.PAY_TYPE_SAFE, false, SafePayPropertyEntity.class);
        String sign = getSign(safePayProperty, callbackEntity);

        log.info(String.format("order no:%scallback result sign compare--callback sign:%s, encryption sign result:%s", callbackEntity.getOrderNo(), callbackEntity.getSign(), sign));
        return sign.equals(callbackEntity.getSign());
    }

    /**
     * 支付请求加密sign
     *
     * @param propertyEntity 配置信息
     * @param depositTable   入金实体
     * @return
     * @throws ServiceException
     */
    private String getSign(SafePayPropertyEntity propertyEntity, FinanceDepositTable depositTable) throws ServiceException {

        BigDecimal amount = getAmount(depositTable);

        String signString = String.format("%s%s%s%s%.0f.00%s%d%s",
                propertyEntity.getPickupUrl(),
                propertyEntity.getReceiveUrl(),
                propertyEntity.getSignType(),
                depositTable.getSerial() + "_" + depositTable.getLogin(),
                amount,
                propertyEntity.getCurrency(),
                depositTable.getCustomId(),
                propertyEntity.getShopKey());
        String sign = MD5Util.getMD5(signString);

        log.info(String.format("orderNo:%s,sign string:%s,sign:%s", depositTable.getId(), signString,
                sign));

        return sign;
    }

    /**
     * 回调请求加密sign
     *
     * @param propertyEntity 配置信息
     * @param callbackEntity 回调实体
     * @return
     * @throws ServiceException
     */
    private String getSign(SafePayPropertyEntity propertyEntity, SafeCallbackEntity callbackEntity) {

        String signString = propertyEntity.getSignType() +
                callbackEntity.getOrderNo() +
                callbackEntity.getOrderPayment() +
                callbackEntity.getOrderCurrency() +
                callbackEntity.getTransactionId() +
                callbackEntity.getStatus() +
                propertyEntity.getShopKey();
        String sign = MD5Util.getMD5(signString);

        log.info(String.format("回调结果加密处理--请求orderNo:%s,sign string:%s,sign:%s", callbackEntity.getOrderNo(),
                signString, sign));

        return sign;
    }

    private BigDecimal getAmount(FinanceDepositTable depositTable) throws ServiceException {
        //获取提交到第三方通道的金额 取值中amount和transformAmount中获取
        BigDecimal amount = null;
        if (PayConstants.SAFE_PAY_CURRENCY.equals(depositTable.getCurrency())) {
            amount = depositTable.getAmount();
        } else if (PayConstants.SAFE_PAY_CURRENCY.equals(depositTable.getTransformCurrency())) {
            amount = depositTable.getTransformAmount();
        } else {
            //如果这两个的货币类型和配置的货币类型全都不一致 提示系统错误
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        return amount;
    }

}
