package cn.fateverse.query.handler.adapter.impl;

import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.query.entity.PortalInterface;
import cn.fateverse.query.entity.PortalMapping;
import cn.fateverse.query.entity.dto.MockParam;
import cn.fateverse.query.entity.bo.PortalBo;
import cn.fateverse.query.enums.PortalEnum;
import cn.fateverse.query.handler.adapter.AbstractDataAdapterHandler;
import cn.fateverse.query.handler.reader.EngineExecuteHandlerReader;
import cn.fateverse.query.mapper.DataAdapterMapper;
import cn.fateverse.query.mapper.PortalInterfaceMapper;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Clay
 * @date 2024/4/19 22:12
 */
@Slf4j
@Service
public class ExternalDataAdapterHandler extends AbstractDataAdapterHandler {

    /**
     * 请求对象
     */
    private final RestTemplate restTemplate;

    private final PortalInterfaceMapper portalInterfaceMapper;

    public ExternalDataAdapterHandler(RestTemplate restTemplate,
                                      DataAdapterMapper dataAdapterMapper,
                                      EngineExecuteHandlerReader handlerReader,
                                      PortalInterfaceMapper portalInterfaceMapper) {
        super(dataAdapterMapper, handlerReader);
        this.restTemplate = restTemplate;
        this.portalInterfaceMapper = portalInterfaceMapper;
    }


    @Override
    public Object mockExecute(PortalBo portal, MockParam mockParam) {
        if (!PortalEnum.EXTERNAL.equals(portal.getType())) {
            return null;
        }
        PortalInterface portalInterface = portalInterfaceMapper.selectById(portal.getInterfaceId());
        if (ObjectUtils.isEmpty(portalInterface)) {
            throw new CustomException("接口不存在");
        }
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType(portalInterface.getContentType());
        headers.setContentType(type);
        Map<String, Object> requestParams = new HashMap<>();
        if (!ObjectUtils.isEmpty(mockParam.getParams())) {
            for (MockParam.Param param : mockParam.getParams()) {
                if (!ObjectUtils.isEmpty(param.getKey()) && !ObjectUtils.isEmpty(param.getValue())) {
                    requestParams.put(param.getKey(), param.getValue());
                }
            }
        }
        JSONObject response = null;
        switch (portalInterface.getRequestMethod()) {
            case "GET":
                response = restTemplate.getForObject(portalInterface.getUrl(), JSONObject.class, requestParams);
                break;
            case "POST":
                response = restTemplate.postForObject(portalInterface.getUrl(), requestParams, JSONObject.class);
                break;
            default:
                throw new CustomException("请求方式错误");
        }
        if (ObjectUtils.isEmpty(portal.getAdapterId()) || !portal.getCreateDataAdapter()) {
            return response;
        } else {
            return super.mockExecute(portal.getAdapterId(), mockParam.getCode(), response);
        }
    }

    @Override
    public Object execute(PortalBo portal, HttpServletRequest request) {
        if (!PortalEnum.EXTERNAL.equals(portal.getType())) {
            return null;
        }
        PortalInterface portalInterface = portalInterfaceMapper.selectById(portal.getInterfaceId());
        if (ObjectUtils.isEmpty(portalInterface)) {
            throw new CustomException("接口不存在");
        }
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType(portalInterface.getContentType());
        headers.setContentType(type);
        Map<String, Object> requestParams = new HashMap<>();
        for (PortalMapping mapping : portal.getMappings()) {
            String mappingValue = mapping.getMappingValue();
            String mappingKey = mapping.getMappingKey();
            if (mapping.getMappingType() == 0) {
                requestParams.put(mappingKey, request.getParameter(mappingValue));
            } else if (mapping.getMappingType() == 1) {
                headers.add(mappingKey, request.getHeader(mappingValue));
            } else {
                requestParams.put(mappingKey, request.getParameter(mappingValue));
            }
        }
        JSONObject response = null;
        switch (portalInterface.getRequestMethod()) {
            case "GET":
                response = restTemplate.getForObject(portalInterface.getUrl(), JSONObject.class, requestParams);
                break;
            case "POST":
                response = restTemplate.postForObject(portalInterface.getUrl(), requestParams, JSONObject.class);
                break;
            default:
                throw new CustomException("请求方式错误");
        }
        if (ObjectUtils.isEmpty(portal.getAdapterId()) || !portal.getCreateDataAdapter()) {
            return response;
        } else {
            return super.execute(portal.getAdapterId(), response);
        }
    }
}
