package ink.wgink.module.wechat.pay.service.v3.impl;

import com.alibaba.fastjson.JSONObject;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.module.wechat.pay.enums.PayErrorMsgEnum;
import ink.wgink.module.wechat.pay.manager.v3.PayManager;
import ink.wgink.module.wechat.pay.pojo.v3.PayErrorResponse;
import ink.wgink.module.wechat.pay.pojo.v3.PayNotice;
import ink.wgink.module.wechat.pay.pojo.v3.PayNoticeCiphertext;
import ink.wgink.module.wechat.pay.service.v3.IPayNoticeService;
import ink.wgink.module.wechat.pay.service.v3.IPayService;
import ink.wgink.module.wechat.pay.utils.v3.PayAesUtil;
import ink.wgink.module.wechat.pay.utils.v3.PayVerifyUtil;
import ink.wgink.properties.wechat.pay.v3.PayProperties;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

/**
 * @ClassName: IPayServiceImpl
 * @Description: 支付
 * @Author: wanggeng
 * @Date: 2021/8/20 8:15 上午
 * @Version: 1.0
 */
@Service
public class PayServiceImpl extends DefaultBaseService implements IPayService {

    @Autowired
    private PayProperties payProperties;
    @Autowired
    private IPayNoticeService payNoticeService;

    @Override
    public void notice(HttpServletRequest request, HttpServletResponse response, String nonce, String timestamp, String wechatpaySignature) throws IOException {
        String payNoticeJsonString = getBodyString(request);
        if (StringUtils.isBlank(payNoticeJsonString)) {
            throw new ParamsException("请求body为空");
        }
        LOG.debug("payNoticeJsonString: {}", payNoticeJsonString);
        PayNotice payNotice = JSONObject.parseObject(payNoticeJsonString, PayNotice.class);
        try {
            LOG.debug("wechatpaySignature: {}", wechatpaySignature);
            LOG.debug("验证签名");
            boolean checkVerify = PayVerifyUtil.verifySignature(wechatpaySignature, payNoticeJsonString, nonce, timestamp, PayManager.getInstance().getPlatformCertificate());
            if (!checkVerify) {
                errorResult(response, PayErrorMsgEnum.SIGN_ERROR_401);
                return;
            }

            LOG.debug("解密内容");
            PayNotice.Resource resource = payNotice.getResource();
            PayAesUtil aesUtil = new PayAesUtil(payProperties.getApiV3Secretkey().getBytes(StandardCharsets.UTF_8));
            String payNoticeCiphertextJsonString = aesUtil.decryptToString(resource.getAssociated_data().getBytes(StandardCharsets.UTF_8), resource.getNonce().getBytes(StandardCharsets.UTF_8), resource.getCiphertext());
            PayNoticeCiphertext payNoticeCiphertext = JSONObject.parseObject(payNoticeCiphertextJsonString, PayNoticeCiphertext.class);
            payNoticeService.handle(payNoticeCiphertext);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            errorResult(response, PayErrorMsgEnum.ERROR_500);
            return;
        }
        successResult(response);
    }


    /**
     * 错误结果
     *
     * @param payErrorMsgEnum
     */
    private void errorResult(HttpServletResponse response, PayErrorMsgEnum payErrorMsgEnum) {
        PayErrorResponse payErrorResponse = new PayErrorResponse();
        payErrorResponse.setCode(payErrorMsgEnum.getErrorCode());
        payErrorResponse.setMessage(payErrorMsgEnum.getSummary());
        response.setContentType("application/json; charset=UTF-8");
        response.setStatus(payErrorMsgEnum.getCode());
        try (PrintWriter writer = response.getWriter()) {
            writer.println(JSONObject.toJSONString(payErrorResponse));
            writer.flush();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    /**
     * 成功结果
     */
    private void successResult(HttpServletResponse response) {
        response.setContentType("application/json; charset=UTF-8");
        response.setStatus(HttpStatus.OK.value());
        JSONObject successJsonObject = new JSONObject();
        successJsonObject.put("code", "SUCCESS");
        successJsonObject.put("message", "成功");
        try (PrintWriter writer = response.getWriter()) {
            writer.println(successJsonObject.toJSONString());
            writer.flush();
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    private String getBodyString(HttpServletRequest request) throws IOException {
        BufferedReader reader = request.getReader();
        StringBuilder bodyString = new StringBuilder();
        for (String line; (line = reader.readLine()) != null; ) {
            bodyString.append(line);
        }
        return bodyString.toString();
    }

}
