package com.lingniu.ingest.protocol.gb32960.inbound;

import com.lingniu.ingest.protocol.gb32960.auth.Gb32960PlatformAuthorizer;
import com.lingniu.ingest.protocol.gb32960.auth.Gb32960VinAuthorizer;
import com.lingniu.ingest.protocol.gb32960.config.Gb32960Properties;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.jupiter.api.Test;

import java.net.InetSocketAddress;
import java.util.List;

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

class Gb32960AccessServiceTest {

    @Test
    void bindPlatformAccount_makesAccountAvailableForLaterFrames() {
        Gb32960AccessService service = newService(false);
        EmbeddedChannel channel = new EmbeddedChannel();

        service.bindPlatformAccount(channel, "lingniu");

        assertThat(service.platformAccount(channel)).isEqualTo("lingniu");
    }

    @Test
    void authenticatePlatformLogin_rejectsUnknownPeerIpWhenPolicyRestrictsIt() {
        Gb32960Properties.Auth auth = new Gb32960Properties.Auth();
        Gb32960Properties.Auth.Platform platform = new Gb32960Properties.Auth.Platform();
        platform.setUsername("lingniu");
        platform.setPassword("secret");
        platform.setAllowedIps(List.of("10.0.0.1"));
        auth.setPlatforms(List.of(platform));

        Gb32960AccessService service = new Gb32960AccessService(
                new Gb32960VinAuthorizer(auth),
                new Gb32960PlatformAuthorizer(auth.getPlatforms()));
        EmbeddedChannel channel = new EmbeddedChannel();
        channel.connect(new InetSocketAddress("10.0.0.2", 9001));

        assertThat(service.authenticatePlatformLogin("lingniu", "secret", channel)
                .accepted()).isFalse();
    }

    @Test
    void authenticatePlatformLogin_ignoresBlankAllowedIps() {
        Gb32960Properties.Auth auth = new Gb32960Properties.Auth();
        Gb32960Properties.Auth.Platform platform = new Gb32960Properties.Auth.Platform();
        platform.setUsername("lingniu");
        platform.setPassword("secret");
        platform.setAllowedIps(List.of("", "  ", "\t"));
        auth.setPlatforms(List.of(platform));

        Gb32960AccessService service = new Gb32960AccessService(
                new Gb32960VinAuthorizer(auth),
                new Gb32960PlatformAuthorizer(auth.getPlatforms()));
        EmbeddedChannel channel = new EmbeddedChannel();
        channel.connect(new InetSocketAddress("115.29.187.205", 9001));

        assertThat(service.authenticatePlatformLogin("lingniu", "secret", channel)
                .accepted()).isTrue();
    }

    @Test
    void authenticatePlatformLogin_acceptsCommaSeparatedAllowedIps() {
        Gb32960Properties.Auth auth = new Gb32960Properties.Auth();
        Gb32960Properties.Auth.Platform platform = new Gb32960Properties.Auth.Platform();
        platform.setUsername("lingniu");
        platform.setPassword("secret");
        platform.setAllowedIps(List.of("115.29.187.205,127.0.0.1"));
        auth.setPlatforms(List.of(platform));

        Gb32960PlatformAuthorizer authorizer = new Gb32960PlatformAuthorizer(auth.getPlatforms());

        assertThat(authorizer.authenticate("lingniu", "secret", "127.0.0.1")
                .accepted()).isTrue();
    }

    private static Gb32960AccessService newService(boolean vinAuthEnabled) {
        Gb32960Properties.Auth auth = new Gb32960Properties.Auth();
        auth.setEnabled(vinAuthEnabled);
        return new Gb32960AccessService(
                new Gb32960VinAuthorizer(auth),
                new Gb32960PlatformAuthorizer(auth.getPlatforms()));
    }
}
