package com.prudas.app.security;

import com.prudas.app.config.AppProperties;
import io.jsonwebtoken.Claims;
import org.junit.jupiter.api.Test;

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

class JwtServiceTest {

    private final AppProperties props = new AppProperties(
            new AppProperties.Cors(java.util.List.of("http://localhost:5173")),
            new AppProperties.Jwt("unit-test-secret-key-at-least-32-characters!!", 15, 7, "prudas-app"),
            new AppProperties.Security(5, 15),
            new AppProperties.RateLimit(5, 10, 10),
            new AppProperties.Recaptcha(false, "", 0.5),
            new AppProperties.Mail(false, "no-reply@prudas.com", "info@prudas.com")
    );

    private final JwtService jwtService = new JwtService(props);

    @Test
    void accessTokenRoundTripsWithExpectedClaims() {
        String token = jwtService.generateAccessToken("admin", "ADMIN");
        Claims claims = jwtService.parseAndValidate(token);

        assertThat(claims.getSubject()).isEqualTo("admin");
        assertThat(claims.get("role", String.class)).isEqualTo("ADMIN");
        assertThat(jwtService.isAccessToken(claims)).isTrue();
        assertThat(jwtService.isRefreshToken(claims)).isFalse();
    }

    @Test
    void refreshTokenIsDistinguishableFromAccessToken() {
        String refresh = jwtService.generateRefreshToken("admin", "ADMIN");
        Claims claims = jwtService.parseAndValidate(refresh);

        assertThat(jwtService.isRefreshToken(claims)).isTrue();
        assertThat(jwtService.isAccessToken(claims)).isFalse();
    }

    @Test
    void tamperedTokenFailsValidation() {
        String token = jwtService.generateAccessToken("admin", "ADMIN");
        String tampered = token.substring(0, token.length() - 2) + "xx";

        assertThat(jwtService.isInvalid(tampered)).isTrue();
        assertThatThrownBy(() -> jwtService.parseAndValidate(tampered)).isInstanceOf(Exception.class);
    }
}
