package com.liquidnet.service.dragon.channel.wepay.strategy.impl;

import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.channel.wepay.resp.WepayPayRespDto;
import com.liquidnet.service.dragon.channel.wepay.strategy.IWepayStrategy;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import com.liquidnet.service.dragon.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;

import java.math.BigDecimal;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @author AnJiabin <anjiabin@zhengzai.tv>
 * @version V1.0
 * @Description: TODO
 * @class: AbstractWepayStrategy
 * @Package com.liquidnet.service.dragon.channel.wepay.strategy.impl
 * @Copyright: LightNet @ Copyright (c) 2021
 * @date 2021/7/11 11:56
 */
@Slf4j
public abstract class AbstractWepayStrategy implements IWepayStrategy {
    @Value("${liquidnet.dragon.wepay.parentKey}")
    private String parentKey;

    @Override
    public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {

        try {
            //构造请求参数
            SortedMap<String, Object> commonParams = this.buildRequestParamMap(dragonPayBaseReqDto);
            //追加请求参数
            SortedMap<String, Object> parameters = appendRequestParam(commonParams);
            //生成签名
            String sign = PayWepayUtils.getInstance().createSign(parameters);
            parameters.put("sign", sign);

            //构造支付请求xml
            String data = PayWepayUtils.getInstance().getRequestXml(parameters);

            HttpPost httpost = new HttpPost(this.getRequestUrl());
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = PayWepayUtils.getInstance().getHttpClient().execute(httpost);
            HttpEntity entity = response.getEntity();
            //接受到返回信息
            String xmlStr = EntityUtils.toString(response.getEntity(), "UTF-8");
            EntityUtils.consume(entity);
            log.info("dragonPay:wepay:wap response xmlStr: {} ",xmlStr);
            WepayPayRespDto respWepayDto= XmlUtil.toBean(xmlStr, WepayPayRespDto.class);

            //构造公共返回参数
            DragonPayBaseRespDto respPayDto = this.buildCommonRespDto(dragonPayBaseReqDto,respWepayDto);
            //构造自定义返回参数
            this.buildResponseDto(respPayDto,respWepayDto);

            return ResponseDto.success(respPayDto);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 构造公共返回参数
     * @param dragonPayBaseReqDto
     * @return
     */
    protected DragonPayBaseRespDto buildCommonRespDto(DragonPayBaseReqDto dragonPayBaseReqDto,WepayPayRespDto respWepayDto){
        DragonPayBaseRespDto respDto = new DragonPayBaseRespDto();
        respDto.setCode(dragonPayBaseReqDto.getCode());
        respDto.setOrderCode(dragonPayBaseReqDto.getOrderCode());
        DragonPayBaseRespDto.PayData payData = new DragonPayBaseRespDto.PayData();
        payData.setAppId(respWepayDto.getAppid());
        payData.setNonceStr(respWepayDto.getNonceStr());
        payData.setPackages("prepay_id="+respWepayDto.getPrepayId());
        payData.setPaySign(respWepayDto.getSign());
        payData.setSignType("MD5");
        payData.setTimeStamp(Long.valueOf(DateUtil.now().getTime()).toString());
        payData.setPartnerId(respWepayDto.getMchId());
        payData.setPrepayId(respWepayDto.getPrepayId());
        respDto.setPayData(payData);
        return respDto;
    }

    /**
     * 构造请求参数
     * @return
     */
    protected SortedMap<String, Object> buildRequestParamMap(DragonPayBaseReqDto dragonPayBaseReqDto){
        String nonceStr = PayWepayUtils.getInstance().getNonceStr();
        SortedMap<String, Object> parameters = new TreeMap<>();
        parameters.put("mch_id", PayWepayUtils.getInstance().getMerchantId());
        parameters.put("nonce_str", nonceStr);
        parameters.put("spbill_create_ip", dragonPayBaseReqDto.getClientIp());
        parameters.put("total_fee", dragonPayBaseReqDto.getPrice().multiply(BigDecimal.valueOf(100L)).intValue());
        parameters.put("body", dragonPayBaseReqDto.getName());
        parameters.put("detail", dragonPayBaseReqDto.getDetail());
        parameters.put("out_trade_no", dragonPayBaseReqDto.getCode());
        String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmssTrim);
        parameters.put("time_expire", timeExpire);
        parameters.put("notify_url", this.getNotifyUrl());
        return parameters;
    };

    /**
     * 追加请求参数
     * @param requestMap
     * @return
     */
    abstract SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap);

    /**
     * 构造返回参数
     */
    abstract DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto,WepayPayRespDto respDto);

    /**
     * 获取请求url
     * @return
     */
    protected abstract String getRequestUrl();

    /**
     * 设置notifyUrl
     */
    protected abstract String getNotifyUrl();
}
