package com.wishurgift.utils;

import com.wishurgift.service.dto.UserDTO;
import io.jsonwebtoken.Claims;
import org.junit.Test;

import static org.junit.Assert.*;

public class JwtUtilsTest {

    private static final String badToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yylOzYIEju5WdXoRkaFUL252-xI5d43MCA5q1o742qU";
    private static final String expiredToken = "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwibmFtZSI6Im5hbWUiLCJlbWFpbCI6ImVtYWlsQGVtYWlsLmNvbSIsInRhZyI6Im5hbWUjMTIzNDUiLCJwdWJsaWMiOmZhbHNlLCJleHAiOjE1ODA4MjU0NDZ9.P793p7EvvHcXetVQw9avhEpWTDm4OpQXHo6rfQZbWOw";

    @Test
    public void generateTokenTest() {
        UserDTO userDTO = makeUserDTO();

        // Generation token et verification de sa validité
        String token = JwtUtils.generate(userDTO);
        assertTrue(JwtUtils.verify(token));
        assertFalse(JwtUtils.verify(badToken));

        // Recupération données dans le payload
        UserDTO actual = JwtUtils.getUser(token);
        assertEquals(userDTO.getId(), actual.getId());
        assertEquals(userDTO.getName(), actual.getName());
        assertEquals(userDTO.getEmail(), actual.getEmail());
        assertEquals(userDTO.getTag(), actual.getTag());
        assertEquals(userDTO.isPublic(), actual.isPublic());
    }

    @Test
    public void getUserTest() {
        // Le token est bien expiré
        assertFalse(JwtUtils.verify(expiredToken));

        // Récupération et verification
        UserDTO user = JwtUtils.getUser(expiredToken, true);
        assertNull(user);

        // Récupération sans validation
        user = JwtUtils.getUser(expiredToken, false);
        assertNotNull(user);
    }

    @Test
    public void getPayloadTest() {
        UserDTO user = makeUserDTO();
        String tag = user.getTag().split("#")[0];
        String token = JwtUtils.generate(user);

        Claims payload = JwtUtils.getPayload(token, true);
        assertNotNull(payload);
        assertEquals(user.getId(), (int) payload.get("id", Integer.class));
        assertEquals(user.getName(), payload.get("name", String.class));
        assertEquals(user.getEmail(), payload.get("email", String.class));
        assertEquals(user.getTag(), payload.get("tag", String.class));
        assertFalse(payload.get("public", Boolean.class));
        assertEquals(tag, payload.getId().substring(0, tag.length()));

        payload = JwtUtils.getPayload(expiredToken, false);
        assertNotNull(payload);
        assertEquals(user.getId(), (int) payload.get("id", Integer.class));
        assertEquals(user.getName(), payload.get("name", String.class));
        assertEquals(user.getEmail(), payload.get("email", String.class));
        assertEquals(user.getTag(), payload.get("tag", String.class));
        assertFalse(payload.get("public", Boolean.class));

        payload = JwtUtils.getPayload(expiredToken, true);
        assertNull(payload);

        payload = JwtUtils.getPayload(badToken, true);
        assertNull(payload);

        payload = JwtUtils.getPayload(badToken, false);
        assertNull(payload);
    }

    @Test
    public void resfreshTest() throws InterruptedException {
        String token = JwtUtils.generate(makeUserDTO());
        Thread.sleep(2000);
        String refresh = JwtUtils.refresh(token);
        assertNotNull(refresh);
        assertNotEquals(token, refresh);
        assertTrue(JwtUtils.verify(token));
        assertTrue(JwtUtils.verify(refresh));
        assertEquals(JwtUtils.getUser(token), JwtUtils.getUser(refresh));

        refresh = JwtUtils.refresh(expiredToken);
        assertNull(refresh);

        refresh = JwtUtils.refresh(badToken);
        assertNull(refresh);
    }

    private UserDTO makeUserDTO() {
        UserDTO user = new UserDTO();
        user.setTag("name#12345");
        user.setName("name");
        user.setEmail("email@email.com");
        user.setPublic(false);
        user.setId(1);
        return user;
    }

}
