package com.ruoyi.app.omgpay;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.net.URI;

@Component
@ConfigurationProperties(prefix = "omgpay")
public class OmgPaymentProperties {
    private static final String APP_RETURN_SCHEME = "com.twanmsdyh.app";
    private static final String APP_RETURN_HOST = "pages";
    private static final String APP_RETURN_PATH = "/OrderList/paySuccess/paySuccess";
    private String returnUrl;
    private String orderResultUrl;
    private String appReturnUrl;

    public String getReturnUrl() {
        return returnUrl;
    }

    public void setReturnUrl(String returnUrl) {
        this.returnUrl = returnUrl;
    }

    public String getOrderResultUrl() {
        return orderResultUrl;
    }

    public void setOrderResultUrl(String orderResultUrl) {
        this.orderResultUrl = orderResultUrl;
    }

    public String getAppReturnUrl() {
        return appReturnUrl;
    }

    public void setAppReturnUrl(String appReturnUrl) {
        this.appReturnUrl = appReturnUrl;
    }

    public String requireSafeReturnUrl() {
        return requireSafeCallbackUrl(returnUrl, "/pay/omg/notify", "ReturnURL");
    }

    public String requireSafeOrderResultUrl() {
        return requireSafeCallbackUrl(orderResultUrl, "/pay/omg/result", "OrderResultURL");
    }

    public String safeAppReturnUrlOrNull() {
        if (appReturnUrl == null || appReturnUrl.isBlank()) {
            return null;
        }
        URI uri;
        try {
            uri = URI.create(appReturnUrl.trim());
        } catch (IllegalArgumentException error) {
            throw new IllegalArgumentException("App return URL is invalid", error);
        }
        if (!APP_RETURN_SCHEME.equalsIgnoreCase(uri.getScheme())
                || !APP_RETURN_HOST.equals(uri.getHost())
                || !APP_RETURN_PATH.equals(uri.getPath())
                || uri.getUserInfo() != null || uri.getQuery() != null || uri.getFragment() != null) {
            throw new IllegalArgumentException("App return URL is unsafe");
        }
        return uri.toASCIIString();
    }

    private static String requireSafeCallbackUrl(String value, String expectedPath, String name) {
        URI uri = requireSafeHttpsUrl(value, "OMG " + name, true);
        if (!expectedPath.equals(uri.getPath())) {
            throw new IllegalArgumentException("OMG " + name + " is unsafe");
        }
        return uri.toASCIIString();
    }

    private static URI requireSafeHttpsUrl(String value, String name, boolean rejectRootPath) {
        if (value == null || value.isBlank()) {
            throw new IllegalArgumentException(name + " is required");
        }
        URI uri;
        try {
            uri = URI.create(value.trim());
        } catch (IllegalArgumentException error) {
            throw new IllegalArgumentException(name + " is invalid", error);
        }
        if (value.trim().length() > 200) {
            throw new IllegalArgumentException(name + " exceeds 200 characters");
        }
        if (!uri.isAbsolute() || !"https".equalsIgnoreCase(uri.getScheme())
                || uri.getHost() == null || uri.getHost().isBlank()
                || uri.getUserInfo() != null || uri.getQuery() != null || uri.getFragment() != null
                || (rejectRootPath && (uri.getPath() == null || "/".equals(uri.getPath())))) {
            throw new IllegalArgumentException(name + " is unsafe");
        }
        return uri;
    }
}
