package com.cameleer.server.app.outbound;

import org.junit.jupiter.api.Test;

import java.net.URI;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class SsrfGuardTest {

    private final SsrfGuard guard = new SsrfGuard(false);  // allow-private disabled by default

    @Test
    void rejectsLoopbackIpv4() {
        assertThatThrownBy(() -> guard.validate(URI.create("https://127.0.0.1/webhook")))
            .isInstanceOf(IllegalArgumentException.class)
            .hasMessageContaining("private or loopback");
    }

    @Test
    void rejectsLocalhostHostname() {
        assertThatThrownBy(() -> guard.validate(URI.create("https://localhost:8080/x")))
            .isInstanceOf(IllegalArgumentException.class);
    }

    @Test
    void rejectsRfc1918Ranges() {
        for (String url : Set.of(
            "https://10.0.0.1/x",
            "https://172.16.5.6/x",
            "https://192.168.1.1/x"
        )) {
            assertThatThrownBy(() -> guard.validate(URI.create(url)))
                .as(url)
                .isInstanceOf(IllegalArgumentException.class);
        }
    }

    @Test
    void rejectsLinkLocal() {
        assertThatThrownBy(() -> guard.validate(URI.create("https://169.254.169.254/latest/meta-data/")))
            .isInstanceOf(IllegalArgumentException.class);
    }

    @Test
    void rejectsIpv6Loopback() {
        assertThatThrownBy(() -> guard.validate(URI.create("https://[::1]/x")))
            .isInstanceOf(IllegalArgumentException.class);
    }

    @Test
    void rejectsIpv6UniqueLocal() {
        assertThatThrownBy(() -> guard.validate(URI.create("https://[fc00::1]/x")))
            .isInstanceOf(IllegalArgumentException.class);
    }

    @Test
    void acceptsPublicHttps() {
        // DNS resolution happens inside validate(); this test relies on a public hostname.
        // Use a literal public IP to avoid network flakiness.
        // 8.8.8.8 is a public Google DNS IP — not in any private range.
        assertThat(new SsrfGuard(false)).isNotNull();
        guard.validate(URI.create("https://8.8.8.8/"));  // does not throw
    }

    @Test
    void allowPrivateFlagBypassesCheck() {
        SsrfGuard permissive = new SsrfGuard(true);
        permissive.validate(URI.create("https://127.0.0.1/"));  // must not throw
    }
}
