package com.ycwl.basic.pay.adapter;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.ycwl.basic.utils.JacksonUtil;
import com.ycwl.basic.pay.entity.CancelOrderRequest;
import com.ycwl.basic.pay.entity.CongMingPayConfig;
import com.ycwl.basic.pay.entity.CreateOrderRequest;
import com.ycwl.basic.pay.entity.CreateOrderResponse;
import com.ycwl.basic.pay.entity.PayResponse;
import com.ycwl.basic.pay.entity.RefundOrderRequest;
import com.ycwl.basic.pay.entity.RefundOrderResponse;
import com.ycwl.basic.pay.entity.RefundResponse;
import com.ycwl.basic.pay.exceptions.PayException;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CongMingPayAdapter implements IPayAdapter {
    private CongMingPayConfig config;
    private static final String MP_PAY_URI = "/api/hFivePay.do";
    private static final String QUERY_ORDER_URI = "/api/query.do";
    private static final String REFUND_ORDER_URI = "/api/refund.do";
    private static final String CANCEL_ORDER_URI = "/api/userCancelOrder.do";

    public CongMingPayAdapter() {

    }

    public CongMingPayAdapter(CongMingPayConfig config) {
        this.config = config;
    }

    @Override
    public void loadConfig(Map<String, String> config) {
        this.config = new CongMingPayConfig();
        this.config.setProgramId(config.get("programId"));
        this.config.setShopId(config.get("shopId"));
        this.config.setApiKey(config.get("apiKey"));
        this.config.setApiHost(config.get("apiHost"));
    }

    @Override
    public CreateOrderResponse createOrder(CreateOrderRequest request) {
        CreateOrderResponse resp = new CreateOrderResponse();
        if (request.getPrice() <= 0) {
            resp.setSkipPay(true);
            return resp;
        }
        String url = config.getApiHost() + MP_PAY_URI;
        Map<String, Object> params = new HashMap<>();
        params.put("program_id", config.getProgramId());
        params.put("shop_id", config.getShopId());
        params.put("money", request.getPriceInYuan().toString());
        params.put("order_id", request.getOrderNo());
        if (StringUtils.isNotBlank(request.getGoodsName())) {
            params.put("goods_msg", request.getGoodsName());
        }
        params.put("device", "AI旅拍");
        params.put("notify_url", request.getNotifyUrl());
        params.put("s_source", "mini_app");
        params.put("sign", parseSign(params, config.getApiKey()));
        System.out.println(url);
        System.out.println(JacksonUtil.toJSONString(params));
        String response = HttpUtil.post(url, JacksonUtil.toJSONString(params));
        Map<String, Object> json = JacksonUtil.parseObject(response, Map.class);
        System.out.println(json);
        if (Strings.CS.equals((String) json.get("result_code"), "fail")) {
            throw new PayException("查询异常！异常提示：" + json.get("error_msg"));
        }
        resp.setSkipPay(false);
        resp.setSuccess(true);
        resp.setOrderNo((String) json.get("order_id"));
        resp.setExtData(JacksonUtil.toJavaObject(json, Map.class));
        return resp;
    }

    @Override
    public Map<String, Object> getPaymentParams(CreateOrderResponse response) {
        Map<String, Object> result = new HashMap<>();
        if (response.isSkipPay()) {
            result.put("skipPay", true);
            return result;
        }
        if (response.getExtData() == null) {
            throw new PayException("查询异常！异常提示：" + "订单信息异常");
        }
        result.put("payWay", "embeddedApp");
        result.put("appId", response.getExtData().get("appid"));
        result.put("path", response.getExtData().get("path"));
        return result;
    }

    @Override
    public PayResponse handleCallback(HttpServletRequest request) throws IOException {
        String moneyStr = request.getParameter("money");
        String orderId = request.getParameter("orderId");
        String resultCode = request.getParameter("result_code");
        PayResponse resp = new PayResponse();
        resp.setPayPriceInYuan(new BigDecimal(moneyStr));
        resp.setOrderNo(orderId);
        if (Strings.CI.equals("success", resultCode)) {
            resp.setState(PayResponse.PAY_STATE.SUCCESS);
        } else {
            resp.setState(PayResponse.PAY_STATE.FAIL);
        }
        resp.setCustomResponse("success");
        return resp;
    }

    @Override
    public PayResponse queryOrder(String orderNo) {
        PayResponse resp = new PayResponse();
        String url = config.getApiHost() + QUERY_ORDER_URI;
        Map<String, Object> params = new HashMap<>();
        params.put("program_id", config.getProgramId());
        params.put("shop_id", config.getShopId());
        params.put("order_id", orderNo);
        params.put("sign", parseSign(params, config.getApiKey()));
        String response = HttpUtil.post(url, JacksonUtil.toJSONString(params));
        Map<String, Object> json = JacksonUtil.parseObject(response, Map.class);
        System.out.println(json);
        if (Strings.CS.equals((String) json.get("result_code"), "fail")) {
            throw new PayException("查询异常！异常提示：" + json.get("error_msg"));
        }
        resp.setOriginalResponse(json);
        resp.setValid(true);
        resp.setOrderPriceInYuan((BigDecimal) json.get("pay_ble"));
        resp.setPayPriceInYuan((BigDecimal) json.get("paid_out"));
        resp.setOrderNo((String) json.get("order_id"));
        switch ((String) json.get("order_status")) {
            case "2":
                resp.setState(PayResponse.PAY_STATE.NOT_PAY);
                break;
            case "1":
                resp.setState(PayResponse.PAY_STATE.SUCCESS);
                resp.setPayTime((String) json.get("time_end"));
                break;
            case "0":
                resp.setState(PayResponse.PAY_STATE.FAIL);
                break;
            default:
                resp.setState(PayResponse.PAY_STATE.CANCEL);
                break;
        }
        return resp;
    }

    @Override
    public RefundOrderResponse refund(RefundOrderRequest request) {
        RefundOrderResponse resp = new RefundOrderResponse();
        if (request.getPrice() <= 0) {
            resp.setSuccess(true);
            return resp;
        }
        String url = config.getApiHost() + REFUND_ORDER_URI;
        Map<String, Object> params = new HashMap<>();
        params.put("program_id", config.getProgramId());
        params.put("shop_id", config.getShopId());
        params.put("shop_order_id", request.getOrderNo());
        params.put("money", request.getRefundPriceInYuan().toString());
        params.put("refund_order_id", request.getRefundNo());
        params.put("sign", parseSign(params, config.getApiKey()));
        String response = HttpUtil.post(url, JacksonUtil.toJSONString(params));
        Map<String, Object> json = JacksonUtil.parseObject(response, Map.class);
        System.out.println(json);
        if (Strings.CI.equals((String) json.get("result_code"), "fail")) {
            throw new PayException("退款异常！异常提示：" + json.get("error_msg"));
        }
        return resp;
    }

    @Override
    public RefundResponse handleRefundCallback(HttpServletRequest request) throws IOException {
        String moneyStr = request.getParameter("money");
        String orderId = request.getParameter("orderId");
        String resultCode = request.getParameter("result_code");
        RefundResponse resp = new RefundResponse();
        resp.setValid(true);
        resp.setRefundPriceInYuan(new BigDecimal(moneyStr));
        resp.setOrderNo(orderId);
        if (Strings.CS.equals("success", resultCode)) {
            resp.setSuccess();
        } else {
            resp.setFail();
        }
        resp.setCustomResponse("success");
        return resp;
    }

    @Override
    public RefundResponse checkRefundStatus(String refundNo) {
        return null;
    }

    @Override
    public void cancelOrder(CancelOrderRequest request) {
        String url = config.getApiHost() + CANCEL_ORDER_URI;
        Map<String, Object> params = new HashMap<>();
        params.put("program_id", config.getProgramId());
        params.put("shop_id", config.getShopId());
        params.put("order_id", request.getOrderNo());
        params.put("error_msg", request.getReason());
        params.put("sign", parseSign(params, config.getApiKey()));
        String response = HttpUtil.post(url, JacksonUtil.toJSONString(params));
        Map<String, Object> json = JacksonUtil.parseObject(response, Map.class);
        if (Strings.CS.equals((String) json.get("result_code"), "fail")) {
            throw new PayException("取消订单异常！异常提示：" + json.get("error_msg"));
        }
    }

    public static String parseSign(Map<String, Object> map, String key) {
        Collection<String> keyset = map.keySet();
        List<String> list = new ArrayList<>(keyset);
        Collections.sort(list);
        StringBuilder signStr = new StringBuilder();
        for (String key1 : list) {
            signStr.append(key1).append("=").append(map.get(key1)).append("&");
        }
        signStr.append("key=").append(key);
        return SecureUtil.md5(signStr.toString()).toUpperCase();
    }
}
