package com.ruoyi.app.omgpay;

import com.ruoyi.app.omgpay.dto.OmgNotifyRequest;
import com.ruoyi.common.utils.ip.IpUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/** Reads the raw form before MVC can discard unknown or empty callback fields. */
@Component
public class OmgNotifyRequestArgumentResolver implements HandlerMethodArgumentResolver {
    private final OmgNotifyFormParser parser;

    public OmgNotifyRequestArgumentResolver(OmgNotifyFormParser parser) {
        this.parser = parser;
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return OmgNotifyRequest.class.equals(parameter.getParameterType())
                && parameter.hasParameterAnnotation(OmgNotifyForm.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        if (request == null) {
            return OmgNotifyFormParser.invalid("unknown", "", "REQUEST_UNAVAILABLE");
        }
        String sourceIp = IpUtils.getIpAddr(request);
        try {
            byte[] body = request.getInputStream().readNBytes(OmgNotifyFormParser.MAX_FORM_BYTES + 1);
            return parser.parse(body, sourceIp, request.getContentType());
        } catch (IOException exception) {
            return OmgNotifyFormParser.invalid(sourceIp,
                    "<request-body-read-error:" + exception.getClass().getSimpleName() + ">",
                    "BODY_READ_FAILED");
        }
    }
}
