package com.cool.store.service.impl;

import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.RandomUtil;
import com.cool.store.dao.StoreDao;
import com.cool.store.dto.FoodTokenDTO;
import com.cool.store.dto.recipe.RecipeSpLaunchDTO;
import com.cool.store.dto.recipe.RevenueDataDTO;
import com.cool.store.dto.recipe.RevenueDataQueryDTO;
import com.cool.store.dto.recipe.SalesVolumeDayQueryDTO;
import com.cool.store.dto.store.StoreUserUpdateDTO;
import com.cool.store.entity.StoreDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.request.recipe.RevenueDataRequest;
import com.cool.store.request.recipe.SalesVolumeDayRequest;
import com.cool.store.response.caipin.StoreUserResponse;
import com.cool.store.response.oppty.OpportunityApiResponse;
import com.cool.store.service.ThirdFoodService;
import com.cool.store.utils.BeanUtil;
import com.cool.store.utils.SignatureUtils;
import com.cool.store.vo.recipe.RevenueDataVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @Author suzhuhong
 * @Date 2025/5/13 15:21
 * @Version 1.0
 */
@Service
@Slf4j
public class ThirdFoodServiceImpl implements ThirdFoodService {

    @Value("${zx.food.url}")
    private String apiUrl;


    @Resource
    OkHttpClient okHttpClient;
    @Resource
    ObjectMapper objectMapper;
    @Resource
    private StoreDao storeDao;


    @Override
    public String getFoodToken(FoodTokenDTO dto) {
        // 1. 发送POST请求
        String url = "/v1/user/getToken";
        return executeApiCall(url, dto, String.class);
    }

    @Override
    public StoreUserResponse pushStoreUser(List<StoreUserUpdateDTO> dto) {
        String url = "/v1/store/updateStoreUser";
        return executeApiCall(url, dto, StoreUserResponse.class);
    }

    @Override
    public List<RevenueDataVO> getRevenueData(RevenueDataRequest request) {
        StoreDO storeDO = storeDao.getByStoreId(request.getStoreId());
        if (Objects.isNull(storeDO)) {
            throw new ServiceException(ErrorCodeEnum.STORE_NOT_FIND);
        }
        RevenueDataQueryDTO queryDTO = new RevenueDataQueryDTO(storeDO.getStoreNum(), request.getBusinessDateFrom(), request.getBusinessDateTo());
        String url = "/v1/store/business";
        List<RevenueDataDTO> list = executeApiCall(url, queryDTO, List.class);
        return BeanUtil.toList(list, RevenueDataVO.class, CopyOptions.create().setFieldMapping(Collections.singletonMap("storeCode", "storeNum")));
    }

    @Override
    public RecipeSpLaunchDTO getRecipeServiceLaunch(RevenueDataRequest request) {
        StoreDO storeDO = storeDao.getByStoreId(request.getStoreId());
        if (Objects.isNull(storeDO)) {
            throw new ServiceException(ErrorCodeEnum.STORE_NOT_FIND);
        }
        RevenueDataQueryDTO queryDTO = new RevenueDataQueryDTO(storeDO.getStoreNum(), request.getBusinessDateFrom(), request.getBusinessDateTo());
        String url = "/v1/store/business/spRecipeList";
        return executeApiCall(url, queryDTO, RecipeSpLaunchDTO.class);
    }

    @Override
    public List<RevenueDataVO> storeSalesVolumeDay(SalesVolumeDayRequest request) {
        StoreDO storeDO = storeDao.getByStoreId(request.getStoreId());
        if (Objects.isNull(storeDO)) {
            throw new ServiceException(ErrorCodeEnum.STORE_NOT_FIND);
        }
        SalesVolumeDayQueryDTO queryDTO = new SalesVolumeDayQueryDTO(request.getBusinessDate(), request.getBusinessDateFrom(), request.getBusinessDateTo(), storeDO.getStoreNum());
        String url = "/v1/store/business/day";
        List<RevenueDataDTO> list = executeApiCall(url, queryDTO, List.class);
        return BeanUtil.toList(list, RevenueDataVO.class, CopyOptions.create().setFieldMapping(Collections.singletonMap("storeCode", "storeNum")));
    }

    private <T> T executeApiCall(String url, Object requestBody, Class<T> responseType) {
        // 1. 打印请求前日志
        //logRequest(url, requestBody);

        try {
            Request request = buildRequest(requestBody, url);

            try (Response response = okHttpClient.newCall(request).execute()) {
                // 2. 获取原始响应内容
                String responseBody = response.body().string();

                // 3. 打印响应日志
                logResponse(apiUrl+ url, response.code(), responseBody);

                if (!response.isSuccessful()) {
                    throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
                            "HTTP请求失败，状态码: " + response.code());
                }

                // 4. 解析响应
                JavaType javaType = objectMapper.getTypeFactory()
                        .constructParametricType(OpportunityApiResponse.class, responseType);

                OpportunityApiResponse<T> apiResponse = objectMapper.readValue(responseBody, javaType);

                if (apiResponse.getCode() != 200) {
                    throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, apiResponse.getMsg());
                }
                return apiResponse.getData();
            }
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("API调用异常 - URL: {}, 错误: {}", url, e.getMessage(), e);
            throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
        }
    }


    private Request buildRequest(Object requestBody, String url) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String random = RandomUtil.randomString(20);

        String signString = null;
        String reqBody = null;
        try {
            reqBody = objectMapper.writeValueAsString(requestBody);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        try {
            signString = SignatureUtils.sign("POST",url, reqBody,timestamp,random);
        } catch (Exception e) {
            throw new ServiceException(ErrorCodeEnum.THIRD_API_SIGN_ERROR,"加密失败");
        }

        log.info("签名生成 - 签名结果: {}", signString);

        RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json"), reqBody);

        return new Request.Builder()
                .url(apiUrl + url)
                .post(body)
                .addHeader("X-ZhengXin-Sign", signString)
                .addHeader("X-ZhengXin-SignTime", timestamp)
                .addHeader("X-ZhengXin-SignRandom", random)
                .addHeader("X-ZhengXin-appId", "CRM")
                .build();
    }

    private void logResponse(String url, int statusCode, String responseBody) {
        if (log.isInfoEnabled()) {
            try {
                // 尝试美化JSON输出
                Object json = objectMapper.readValue(responseBody, Object.class);
                String prettyResponse = objectMapper.writerWithDefaultPrettyPrinter()
                        .writeValueAsString(json);

                log.info("\n======= 响应开始 =======\n" +
                                "API地址: {}\n" +
                                "HTTP状态码: {}\n" +
                                "响应内容: {}\n" +
                                "======= 响应结束 =======",
                        url,
                        statusCode,
                        prettyResponse);
            } catch (Exception e) {
                // 非JSON响应或解析失败时直接输出原始内容
                log.info("\n======= 响应开始 =======\n" +
                                "API地址: {}\n" +
                                "HTTP状态码: {}\n" +
                                "原始响应: {}\n" +
                                "======= 响应结束 =======",
                        url,
                        statusCode,
                        responseBody);
            }
        }
    }
}
