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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.crm.pay.entity.callback.KonnexoyCallbackEntity;
import com.crm.pay.entity.konnexpy.KonnexpyTicketEntity;
import com.crm.pay.entity.property.KonnexpyPropertyEntity;
import com.crm.pay.service.CustomInfoService;
import com.crm.pay.service.FinanceDepositService;
import com.crm.pay.service.KonnexpyService;
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.CustomInfoTable;
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.PayValidatedException;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.util.Base64Util;
import com.crm.rely.backend.util.HttpUtil;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: cwg-my-base
 * @description:
 * @author: houn
 * @create: 2021-05-31 11:45
 */
@Slf4j
@Service
public class KonnexpyServiceImpl extends BasePayServiceImpl implements KonnexpyService {

    @Autowired
    private FinanceDepositService financeDepositService;

    @Autowired
    private CustomInfoService customInfoService;

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

        //通道配置
        SysRemittanceChannelTable channel = this.getPayChannel(PayConstants.KONNEXPY_PAY);
        //通道配置实体
        KonnexpyPropertyEntity payProperty = this.getPayProperty(channel, KonnexpyPropertyEntity.class);

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

        FinanceDepositTable balanceTable = this.financeDepositService.save(balanceSaveEntity, channel);

        String ticket = this.getTicket(payProperty, balanceTable, balanceSaveEntity);
        balanceTable.setChannelSerial(ticket);
        
        return payProperty.getPickupUrl();
    }

    /**
     * 回调处理数据
     *
     * @param callbackEntity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void callback(KonnexoyCallbackEntity callbackEntity) throws Exception {
        log.info(String.format("callback ticket:%s,callback data:%s", callbackEntity.getTicket(),
                JSON.toJSONString(callbackEntity)));
        //获取配置
        KonnexpyPropertyEntity payProperty = this.getPayProperty(PayConstants.KONNEXPY_PAY, false,
                KonnexpyPropertyEntity.class);

        KonnexpyTicketEntity konnexpyTicketEntity = this.getTicketData(payProperty, callbackEntity.getTicket());
        int status;
        switch (konnexpyTicketEntity.getStatus()) {
            case PayConstants.KONNEXPY_CONFIRMED_STATUS:
            case PayConstants.KONNEXPY_COMPLETED_STATUS:
                status = PayConstants.CALLBACE_SUCCESS_STATUS;
                break;
            case PayConstants.KONNEXPY_CANCELED_STATUS:
                status = PayConstants.CALLBACE_FAIL_STATUS;
                break;
            default:
                status = 0;
                break;
        }

        FinanceDepositCallbackUpdateEntity balanceCallbackUpdateEntity = new FinanceDepositCallbackUpdateEntity();
        balanceCallbackUpdateEntity.setChannelSerial(callbackEntity.getTicket());
        balanceCallbackUpdateEntity.setTicket(callbackEntity.getTicket());
        balanceCallbackUpdateEntity.setCallbackStatus(status);
        balanceCallbackUpdateEntity.setCallbackTime(new Date());
        balanceCallbackUpdateEntity.setCallbackData(JSON.toJSONString(callbackEntity));
        balanceCallbackUpdateEntity.setAmount(new BigDecimal(konnexpyTicketEntity.getAmount()));

        /**
         * 更新数据
         */
        financeDepositService.updateCallback(balanceCallbackUpdateEntity);
    }

    /**
     * 获取支付url
     *
     * @param balanceTable
     * @return
     * @throws ServiceException
     */
    private String getTicket(KonnexpyPropertyEntity propertyEntity, FinanceDepositTable balanceTable,
                             FinanceDepositAddEntity balanceSaveEntity) throws ServiceException, IOException,
            PayValidatedException {

        String orderNo = balanceTable.getSerial() + "_" + balanceTable.getLogin();

        CustomInfoTable customInfoTable = this.customInfoService.getById(balanceTable.getCustomId());

        Map<String, String> header = new HashMap<>(2);

        header.put("Content-Type", "application/x-www-form-urlencoded");
        header.put("Authorization",
                propertyEntity.getAuthorizationBasic() + Base64Util.toBase64String(propertyEntity.getUsername() + ":" + propertyEntity.getApiKey()));

        Map<String, String> params = new HashMap<>(3);
        params.put("email", customInfoTable.getEmail());
        params.put("account", orderNo);
        params.put("amount", String.format("%.2f", balanceTable.getTransformAmount().doubleValue()));

        Connection.Response response = HttpUtil.post(header,
                propertyEntity.getBaseUrl() + propertyEntity.getDepositUel(), params);

        log.info(String.format("url:%s,header:%s,params:%s,body:%s",
                propertyEntity.getBaseUrl() + propertyEntity.getDepositUel(),
                JSON.toJSON(header), JSON.toJSON(params), response.body()));
        JSONObject requestEntity = JSON.parseObject(response.body());

        if (requestEntity == null) {
            throw new PayValidatedException("Payment platform is abnormal, please try again later or contact customer" +
                    " service.");
        }

        if (Strings.isNullOrEmpty(requestEntity.getString("ticket"))) {
            if (Strings.isNullOrEmpty(requestEntity.getString("message"))) {
                throw new PayValidatedException("Payment platform is abnormal, please try again later or contact " +
                        "customer" +
                        " service.");
            } else {
                throw new PayValidatedException(requestEntity.getString("message"));
            }
        }
        log.info(String.format("支付请求,请求orderNo:%s,ticket:%s", orderNo, requestEntity.getString("ticket")));
        return requestEntity.getString("ticket");
    }

    private KonnexpyTicketEntity getTicketData(KonnexpyPropertyEntity propertyEntity, String ticket) throws ServiceException,
            IOException,
            PayValidatedException {

        Map<String, String> header = new HashMap<>(2);

        header.put("Content-Type", "application/x-www-form-urlencoded");
        header.put("Authorization",
                propertyEntity.getAuthorizationBasic() + Base64Util.toBase64String(propertyEntity.getUsername() + ":" + propertyEntity.getApiKey()));
        String url = propertyEntity.getBaseUrl() + propertyEntity.getTransactionUel() + "?ticket=" + ticket;
        Connection.Response response = HttpUtil.get(url, header);

        log.info(String.format("get ticket data, url:%s,header:%s,body:%s",
                url, JSON.toJSONString(header), response.body()));
        List<KonnexpyTicketEntity> requestEntity = JSON.parseArray(response.body(), KonnexpyTicketEntity.class);

        if (requestEntity == null) {
            throw new PayValidatedException("Payment platform is abnormal, please try again later or contact customer" +
                    " service.");
        }
        KonnexpyTicketEntity konnexpyTicketEntity = requestEntity.get(0);
        if (!Strings.isNullOrEmpty(konnexpyTicketEntity.getMessage())) {

            throw new PayValidatedException(konnexpyTicketEntity.getMessage());

        }
        return konnexpyTicketEntity;
    }

    public static void main(String[] args) {
//        System.out.println(AESUtil.encrypt("", "bfa5559109f94c78af615bcf00d52060"));
//
//        System.out.println(AESUtil.decrypt("", "bfa5559109f94c78af615bcf00d52060"));
        String jsonString = "[{\"Ticket\":136789,\"UserName\":\"API USER\",\"ResellerName\":\"Konnexone Korea Inc.\"," +
                "\"MerchantName\":\"CWG " +
                "Markets Limited\",\"MerchantAccount\":\"PD202302221201199143_66703012\",\"SourceMerchantName\":null," +
                "\"SourceMerchantAccount\":\"\",\"TransactionType\":\"deposit\",\"Amount\":100,\"Currency\":\"KRW\"," +
                "\"CurrencyAmount\":134880,\"Exchange\":1315.9,\"FeeRate\":2.5,\"Fee\":2.5,\"Status\":1," +
                "\"UserComment\":\"API" +
                " Transaction\",\"ResellerComment\":\"\",\"MerchantComment\":\"\",\"ResellerSettingDate\":\"2/22/2023" +
                " 5:02:56" +
                " PM\",\"MerchantSettingDate\":null,\"RegistrationDate\":\"2/22/2023 5:01:19 PM\"}]";
        List<KonnexpyTicketEntity> requestEntity = JSON.parseArray(jsonString, KonnexpyTicketEntity.class);

        System.out.println(requestEntity);
    }
}
