package dev.sonpx.loyalty.mcp.config;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.service.invoker.HttpRequestValues;
import org.springframework.web.service.invoker.HttpServiceArgumentResolver;
import org.springframework.data.domain.Pageable;

import java.util.Map;

public class PojoArgumentResolver implements HttpServiceArgumentResolver {
    private final ObjectMapper objectMapper;

    public PojoArgumentResolver() {
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public boolean resolve(Object argument, MethodParameter parameter, HttpRequestValues.Builder requestValues) {
        // Skip if parameter is annotated with typical HTTP interface annotations
        if (parameter.hasParameterAnnotation(RequestParam.class) ||
            parameter.hasParameterAnnotation(RequestBody.class) ||
            parameter.hasParameterAnnotation(PathVariable.class)) {
            return false;
        }
        
        // Skip basic types and Pageable
        if (parameter.getParameterType().isPrimitive() || 
            parameter.getParameterType().getName().startsWith("java.lang") ||
            Pageable.class.isAssignableFrom(parameter.getParameterType())) {
            return false;
        }

        if (argument == null) {
            return true;
        }

        Map<String, Object> map = objectMapper.convertValue(argument, new TypeReference<>() {});
        flattenMap("", map, requestValues);
        return true;
    }

    private void flattenMap(String prefix, Map<String, Object> map, HttpRequestValues.Builder requestValues) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> nestedMap = (Map<String, Object>) value;
                flattenMap(key, nestedMap, requestValues);
            } else if (value instanceof Iterable<?> iterable) {
                for (Object item : iterable) {
                    if (item != null) {
                        requestValues.addRequestParameter(key, String.valueOf(item));
                    }
                }
            } else if (value != null) {
                requestValues.addRequestParameter(key, String.valueOf(value));
            }
        }
    }
}
