package com.fs.erp.http;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.fs.erp.dto.*;
import com.fs.erp.service.impl.JstTokenService;
import com.fs.erp.utils.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class JstErpHttpServiceImpl implements JstErpHttpService {

    private static final String BASE_URL = "https://openapi.jushuitan.com/";
    /**
     * 获取access_token、refresh_token url
     */
    private static final String GET_INIT_TOKEN_URL = BASE_URL + "openWeb/auth/getInitToken";

    /**
     * 更新access_token、refresh_token url
     */
    private static final String REFRESH_TOKEN_URL = BASE_URL + "openWeb/auth/refreshToken";


    @Value("${jst.app_key}")
    private String appKey;

    @Value("${jst.app_secret}")
    private String appSecret;

    @Autowired
    private JstTokenService jstTokenService;

    @Override
    public GetInitTokenResponseDTO getInitToken(GetInitTokenRequestDTO dto) {
        // 将DTO转换为表单参数
        Map<String, Object> formParams = BeanUtil.beanToMap(dto);
        log.info("请求初始化token - URL: {}, 参数: {}", GET_INIT_TOKEN_URL, JSON.toJSONString(formParams));

        HttpResponse response = executeJsonPost(GET_INIT_TOKEN_URL, formParams);
        return parseResponse(response, new TypeReference<CommonResponse<GetInitTokenResponseDTO>>() {});
    }

    @Override
    public GetInitTokenResponseDTO refreshToken(RefreshTokenRequestDTO dto) {
        log.info("刷新token - URL: {}, 请求体: {}", REFRESH_TOKEN_URL, JSON.toJSONString(dto));

        HttpResponse response = executeJsonPost(REFRESH_TOKEN_URL, dto);
        return parseResponse(response, new TypeReference<CommonResponse<GetInitTokenResponseDTO>>() {});
    }

    @Override
    public ProductUploadResultDTO uploadGoods(GoodsInfoDTO dto) {
        String url = BASE_URL + "/open/jushuitan/itemsku/upload";
        log.info("上传商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));

        HttpResponse response = executeJsonPost(url, dto);
        return parseResponse(response, new TypeReference<CommonResponse<ProductUploadResultDTO>>() {});
    }

    @Override
    public ProductResponseDTO queryGoods(ProductQueryRequestDTO dto) {
        String url = BASE_URL + "/open/sku/query";
        log.info("查询商品信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));

        HttpResponse response = executeJsonPost(url, dto);
        return parseResponse(response, new TypeReference<CommonResponse<ProductResponseDTO>>() {});
    }

    @Override
    public ErpOrderResponseDTO upload(ShopOrderDTO dto) {
        String url = BASE_URL + "open/jushuitan/orders/upload";
        log.info("上传订单信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));

        HttpResponse response = executeJsonPost(url, Arrays.asList(dto));
        return parseResponse(response, new TypeReference<CommonResponse<ErpOrderResponseDTO>>() {});
    }

    @Override
    public OrderQueryResponseDTO query(OrderQueryRequestDTO dto) {
        String url = BASE_URL + "/open/orders/single/query";
        log.info("查询订单信息 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));

        HttpResponse response = executeJsonPost(url, dto);
        return parseResponse(response, new TypeReference<CommonResponse<OrderQueryResponseDTO>>() {});
    }

    @Override
    public CommonResponse cancel(OrderCancelRequestDTO dto) {
        String url = BASE_URL + "/open/jushuitan/orderbyoid/cancel";
        log.info("取消订单 - URL: {}, 请求体: {}", url, JSON.toJSONString(dto));

        HttpResponse response = executeJsonPost(url, dto);
        // 这里直接返回CommonResponse类型
        return parseCommonResponse(response);
    }

    /**
     * 执行JSON格式的POST请求
     *
     * @param url 请求URL
     * @param dto 请求对象
     * @return HttpResponse响应
     */
    private HttpResponse executeJsonPost(String url, Object dto) {
        SerializeConfig serializeConfig = new SerializeConfig();
        serializeConfig.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;

        String jsonBody = JSON.toJSONString(dto, serializeConfig);

        Map<String,Object> map = new HashMap<>();

        String accessToken = jstTokenService.getAccessToken();

        map.put("access_token",accessToken);
        map.put("app_key",appKey);
        map.put("timestamp",System.currentTimeMillis()/1000);
        map.put("version","2");
        map.put("charset","utf-8");
        map.put("biz", jsonBody);

        map.put("sign",SignUtil.getSignNew(appSecret, map));


        Map<String, String> headers = MapUtil.builder(new HashMap<String, String>())
                .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
                .build();


        log.debug("发送JSON请求 - URL: {}, Headers: {}, Body: {}", url, headers, JSON.toJSONString(map));

        HttpResponse response = HttpRequest.post(url)
                .headerMap(headers, true)
                .form(map)
                .execute();

        logResponse(response);
        return response;
    }


    /**
     * 执行表单格式的POST请求
     *
     * @param url 请求URL
     * @param formParams 表单参数
     * @return HttpResponse响应
     */
    private HttpResponse executeFormPost(String url, Map<String, Object> formParams) {
        Map<String, String> headers = MapUtil.builder(new HashMap<String, String>())
                .put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
                .build();

        log.debug("发送表单请求 - URL: {}, Headers: {}, Form: {}", url, headers, formParams);

        HttpResponse response = HttpRequest.post(url)
                .headerMap(headers, true)
                .form(formParams)
                .execute();

        logResponse(response);
        return response;
    }

    /**
     * 记录HTTP响应日志
     *
     * @param response HTTP响应
     */
    private void logResponse(HttpResponse response) {
        log.debug("收到响应 - Status: {}, Headers: {}", response.getStatus(), response.headers());
        log.debug("响应体: {}", response.body());
    }

    /**
     * 解析带有泛型的HTTP响应
     *
     * @param response HTTP响应
     * @param typeReference 响应类型引用
     * @param <T> 期望的响应数据类型
     * @return 解析后的数据
     */
    private <T> T parseResponse(HttpResponse response, TypeReference<CommonResponse<T>> typeReference) {
        String body = response.body();
        log.debug("解析响应体: {}", body);

        CommonResponse<T> commonResponse = JSON.parseObject(body, typeReference);

        if (ObjectUtils.notEqual(commonResponse.getCode(), 0)) {
            log.error("API请求失败 - 错误码: {}, 错误信息: {}", commonResponse.getCode(), commonResponse.getMsg());
            throw new RuntimeException("请求接口失败！原因：" + commonResponse.getMsg());
        }

        T result = commonResponse.getData();
        log.info("API请求成功 - 结果: {}", JSON.toJSONString(result));
        return result;
    }

    /**
     * 解析普通CommonResponse响应（无泛型）
     *
     * @param response HTTP响应
     * @return CommonResponse对象
     */
    private CommonResponse parseCommonResponse(HttpResponse response) {
        String body = response.body();
        log.debug("解析响应体: {}", body);

        CommonResponse commonResponse = JSON.parseObject(body, CommonResponse.class);

        if (ObjectUtils.notEqual(commonResponse.getCode(), 0)) {
            log.error("API请求失败 - 错误码: {}, 错误信息: {}", commonResponse.getCode(), commonResponse.getMsg());
            throw new RuntimeException("请求接口失败！原因：" + commonResponse.getMsg());
        }

        log.info("API请求成功 - 结果: {}", JSON.toJSONString(commonResponse));
        return commonResponse;
    }
}
