package com.ruoyi.app.utils.zaloPay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.app.utils.zaloPayCrypto.HMACUtil;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * ZaloPay 工具类
 *
 * @author ruoyi
 **/
@Component
public class ZaloPay {
    @Autowired
    private ZaloPayApiProperties apiProperties;

    /**
     * 生成 HMAC SHA256 签名
     */

    public static String getCurrentTimeString(String format) {
        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT+7"));
        SimpleDateFormat fmt = new SimpleDateFormat(format);
        fmt.setCalendar(cal);
        return fmt.format(cal.getTimeInMillis());
    }

    /**
     * 创建ZaloPay订单，返回支付链接
     *
     * @param userId      用户唯一标识
     * @param orderId     订单号（建议格式：yymmdd_唯一编号）
     * @param amount      金额（单位：VND）
     * @param description 订单描述
     * @return ZaloPayCreateOrderResponse 支付响应数据
     */
    public  ZaloPayCreateOrderResponse createOrder(String userId, String orderId, long amount, String description,ZaloPayProperties.ZaloPayConfig config) throws Exception {
//        ZaloPayConfig config = ZaloPayConfig.getZaloPayConfig(payType);
        String APP_ID = config.getApp_id();
        String KEY1 = config.getKey1();

        System.out.println("进入zalopay CreateOrder orderId: " + orderId+" amount: " + amount);
        // 从传入参数构建 embed_data
        final Map<String, Object> embed_data = new HashMap<>();
        // 如果有实际需要，可以在这里添加字段

        // 从传入参数构建 item 列表
        final List<Map<String, Object>> items = new ArrayList<>();
        // 示例：添加一个商品项
        Map<String, Object> item = new HashMap<>();

//        item.put("item_price", amount / 100); // 假设金额以分为单位
//        items.add(item);

        String appTransId =getCurrentTimeString("yyMMdd") + "_" + orderId;
        Map<String, Object> order = new HashMap<String, Object>(){{
            put("app_id", APP_ID);
            put("app_trans_id", appTransId);
            put("app_time", System.currentTimeMillis()); //毫米级时间戳，时间戳与时区无关 miliseconds
            put("app_user", userId);
            put("amount", amount);
            put("description", description);
            //钱包支付
            if(config.getPay_type().equals("3")){
                put("bank_code", "zalopayapp");
                put("embed_data", "{}");
            }
            //银行卡支付
            if(config.getPay_type().equals("5")){
                put("bank_code", "");
                put("embed_data", "{\"preferred payment method\":[\"domestic card\",\"account\"],\"redirecturl\":\"cityexpressuser://\"}");
            }
            if(config.getPay_type().equals("4")){
                put("bank_code", "");
                put("embed_data", "{\"preferred payment method\":[\"vietqr\"],\"redirecturl\":\"cityexpressuser://\"}");
            }

            put("item", "[]");

        }};


        String data = order.get("app_id") +"|"+ order.get("app_trans_id") +"|"+ order.get("app_user") +"|"+ order.get("amount")
                +"|"+ order.get("app_time") +"|"+ order.get("embed_data") +"|"+ order.get("item");
        order.put("mac", HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data));
        System.out.println("ZaloPay CreateOrder 创建的 order信息: " + order);
        HttpPost post=createPost(order, apiProperties.getCreate_order_url());

        // 添加日志和异常处理
        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse res = httpClient.execute(post)) {

            BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
            StringBuilder resultJsonStr = new StringBuilder();
            String line;

            while ((line = rd.readLine()) != null) {
                resultJsonStr.append(line);
            }
            String responseJson = resultJsonStr.toString();
            System.out.println("ZaloPay CreateOrder Response: " + responseJson); // 日志输出
            return JSON.parseObject(responseJson, ZaloPayCreateOrderResponse.class);
        }
    }
    /**
     * 查询订单支付状态
     *
     * @param appTransId 订单号
     * @return 支付状态
     */
    public  ZaloPayQueryOrderResponse queryOrderStatus(String appTransId,ZaloPayProperties.ZaloPayConfig config) throws URISyntaxException, IOException {
        String APP_ID = config.getApp_id();
        String KEY1 = config.getKey1();
        String data = APP_ID +"|"+ appTransId  +"|"+ KEY1; // appid|app_trans_id|key1
        String mac = HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data);

        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("app_id", APP_ID));
        params.add(new BasicNameValuePair("app_trans_id", appTransId));
        params.add(new BasicNameValuePair("mac", mac));
        URIBuilder uri = new URIBuilder(apiProperties.getQuery_order_url());
        uri.addParameters(params);
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(uri.build());
        post.setEntity(new UrlEncodedFormEntity(params));
        CloseableHttpResponse res = client.execute(post);
        BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
        StringBuilder resultJsonStr = new StringBuilder();
        String line;
        while ((line = rd.readLine()) != null) {
            resultJsonStr.append(line);
        }
        JSONObject result = JSON.parseObject(resultJsonStr.toString());
        for (String key : result.keySet()) {
            System.out.format("%s = %s\n", key, result.get(key));
        }
        System.out.println("ZaloPay QueryOrder Response: " + resultJsonStr);
        return JSON.parseObject(resultJsonStr.toString(), ZaloPayQueryOrderResponse.class);
    }

    /**
     * 退款
     *
     * @param zpTransId
     * @param amount
     * @return ZaloPayRefundResponse 退款响应数据
     */
    public  ZaloPayRefundResponse Refund(String zpTransId, long amount,String mRefundId,ZaloPayProperties.ZaloPayConfig config) throws Exception {
        String APP_ID = config.getApp_id();
        String KEY1 = config.getKey1();
        String appid = APP_ID;
        long timestamp = System.currentTimeMillis(); // miliseconds
        Map<String, Object> order = new HashMap<String, Object>() {{
            put("app_id", appid);
            put("zp_trans_id", zpTransId); // 使用传入的 zpTransId
//            put("m_refund_id", getCurrentTimeString("yyMMdd") + "_" + appid + "_" + ddId);
            put("m_refund_id", mRefundId);
            put("timestamp", timestamp);
            put("amount", amount); // 使用传入的 amount
            put("description", "ZaloPay Intergration Demo");
        }};

        // appid|zptransid|amount|description|timestamp
        String data = order.get("app_id") + "|" + order.get("zp_trans_id") + "|" + order.get("amount")
                + "|" + order.get("description") + "|" + order.get("timestamp");
        order.put("mac", HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data));

        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = createPost(order, apiProperties.getRefund_url());
        CloseableHttpResponse res = client.execute(post);
        BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
        StringBuilder resultJsonStr = new StringBuilder();
        String line;

        while ((line = rd.readLine()) != null) {
            resultJsonStr.append(line);
        }
        System.out.println("ZaloPay Refund Response: " + resultJsonStr.toString()); // 日志输出
        // 解析响应数据为 ZaloPayRefundResponse 对象
        return JSON.parseObject(resultJsonStr.toString(), ZaloPayRefundResponse.class);
    }
    /**
     * 查询退款状态
     *
     * @param m_refund_id 退款单号
     * @return 退款状态
     */
    public  ZaloPayQueryRefundResponse queryRefundStatus(String m_refund_id, ZaloPayProperties.ZaloPayConfig config) throws URISyntaxException, IOException {
        String APP_ID = config.getApp_id();
        String KEY1 = config.getKey1();
        String timestamp = Long.toString(System.currentTimeMillis()); // miliseconds
        String data = APP_ID +"|"+ m_refund_id  +"|"+ timestamp; // app_id|m_refund_id|timestamp
        String mac = HMACUtil.HMacHexStringEncode(HMACUtil.HMACSHA256, KEY1, data);

        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("app_id", APP_ID));
        params.add(new BasicNameValuePair("m_refund_id", m_refund_id));
        params.add(new BasicNameValuePair("timestamp", timestamp));
        params.add(new BasicNameValuePair("mac", mac));
        URIBuilder uri = new URIBuilder(apiProperties.getQuery_refund_url());
        uri.addParameters(params);

        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(uri.build());
        post.setEntity(new UrlEncodedFormEntity(params));

        CloseableHttpResponse res = client.execute(post);
        BufferedReader rd = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
        StringBuilder resultJsonStr = new StringBuilder();
        String line;

        while ((line = rd.readLine()) != null) {
            resultJsonStr.append(line);
        }
        System.out.println("ZaloPay QueryRefund Response: " + resultJsonStr);
        return JSON.parseObject(resultJsonStr.toString(), ZaloPayQueryRefundResponse.class);
    }


    public static HttpPost createPost(Map<String, Object> order, String refundUrl) throws UnsupportedEncodingException {
        HttpPost post = new HttpPost(refundUrl);

        List<NameValuePair> params = new ArrayList<>();
        for (Map.Entry<String, Object> e : order.entrySet()) {
            params.add(new BasicNameValuePair(e.getKey(), e.getValue().toString()));
        }

        post.setEntity(new UrlEncodedFormEntity(params));
        return post;
    }
}
