package org.pac4j.cas.client.rest;

import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.junit.Test;
import org.pac4j.cas.credentials.authenticator.CasRestAuthenticator;
import org.pac4j.cas.profile.CasRestProfile;
import org.pac4j.cas.profile.CasProfile;
import org.pac4j.core.context.HttpConstants;
import org.pac4j.core.context.MockWebContext;
import org.pac4j.core.credentials.TokenCredentials;
import org.pac4j.core.exception.HttpAction;
import org.pac4j.core.exception.TechnicalException;
import org.pac4j.core.util.TestsConstants;
import org.pac4j.core.credentials.UsernamePasswordCredentials;
import org.pac4j.core.credentials.authenticator.Authenticator;
import org.pac4j.core.credentials.authenticator.LocalCachingAuthenticator;
import org.pac4j.core.util.TestsHelper;

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

/**
 * Tests the {@link CasRestBasicAuthClient} and {@link CasRestFormClient}.
 *
 * @author Misagh Moayyed
 * @since 1.8.0
 */
public final class CasRestClientIT implements TestsConstants {

    private final static String CAS_PREFIX_URL = "http://casserverpac4j.herokuapp.com/";

    @Test
    public void testRestForm() throws HttpAction {
        internalTestRestForm(new CasRestAuthenticator(CAS_PREFIX_URL));
    }

    @Test
    public void testRestFormWithCaching() throws HttpAction {
        internalTestRestForm(new LocalCachingAuthenticator<>(new CasRestAuthenticator(CAS_PREFIX_URL), 100, 100, TimeUnit.SECONDS));
    }

    private void internalTestRestForm(final Authenticator authenticator) throws HttpAction {
        final CasRestFormClient client = new CasRestFormClient();
        client.setAuthenticator(authenticator);

        final MockWebContext context = MockWebContext.create();
        context.addRequestParameter(client.getUsernameParameter(), USERNAME);
        context.addRequestParameter(client.getPasswordParameter(), USERNAME);

        final UsernamePasswordCredentials credentials = client.getCredentials(context);
        final CasRestProfile profile = client.getUserProfile(credentials, context);
        assertEquals(USERNAME, profile.getId());
        assertNotNull(profile.getTicketGrantingTicketId());

        final TokenCredentials casCreds = client.requestServiceTicket(PAC4J_BASE_URL, profile);
        final CasProfile casProfile = client.validateServiceTicket(PAC4J_BASE_URL, casCreds);
        assertNotNull(casProfile);
        assertEquals(USERNAME, casProfile.getId());
        assertTrue(casProfile.getAttributes().size() > 0);
    }

    @Test
    public void testRestBasic() throws HttpAction, UnsupportedEncodingException {
        internalTestRestBasic(new CasRestBasicAuthClient(CAS_PREFIX_URL, VALUE, NAME), 3);
    }

    @Test
    public void testRestBasicWithCas20TicketValidator() throws HttpAction, UnsupportedEncodingException {
        final CasRestAuthenticator authenticator = new CasRestAuthenticator(CAS_PREFIX_URL);
        authenticator.setTicketValidator(new Cas20ServiceTicketValidator(CAS_PREFIX_URL));
        internalTestRestBasic(new CasRestBasicAuthClient(authenticator, VALUE, NAME), 0);
    }

    private void internalTestRestBasic(final CasRestBasicAuthClient client, int nbAttributes) throws HttpAction, UnsupportedEncodingException {
        final MockWebContext context = MockWebContext.create();
        final String token = USERNAME + ":" + USERNAME;
        context.addRequestHeader(VALUE, NAME + Base64.getEncoder().encodeToString(token.getBytes(HttpConstants.UTF8_ENCODING)));

        final UsernamePasswordCredentials credentials = client.getCredentials(context);
        final CasRestProfile profile = client.getUserProfile(credentials, context);
        assertEquals(USERNAME, profile.getId());
        assertNotNull(profile.getTicketGrantingTicketId());

        final TokenCredentials casCreds = client.requestServiceTicket(PAC4J_BASE_URL, profile);
        final CasProfile casProfile = client.validateServiceTicket(PAC4J_BASE_URL, casCreds);
        assertNotNull(casProfile);
        assertEquals(USERNAME, casProfile.getId());
        assertEquals(nbAttributes, casProfile.getAttributes().size());
        client.destroyTicketGrantingTicket(profile);

        TestsHelper.expectException(() -> client.requestServiceTicket(PAC4J_BASE_URL, profile), TechnicalException.class,
                "Service ticket request for `#CasRestProfile# | id: username | attributes: {} | roles: [] | permissions: [] | isRemembered: false |` failed: (404) Not Found");
    }
}

@@ -1223,16 +1223,65 @@
 p.com/%22;
+%0A    private final static String USER = %22jleleu%22;
 %0A%0A    @T
@@ -1969,20 +1969,16 @@
 (), USER
-NAME
 );%0A     
@@ -2043,20 +2043,16 @@
 (), USER
-NAME
 );%0A%0A    
@@ -2236,36 +2236,32 @@
 ssertEquals(USER
-NAME
 , profile.getId(
@@ -2567,36 +2567,32 @@
 ssertEquals(USER
-NAME
 , casProfile.get
@@ -2847,9 +2847,9 @@
 E), 
-3
+5
 );%0A 
@@ -3492,20 +3492,16 @@
 n = USER
-NAME
  + %22:%22 +
@@ -3505,20 +3505,16 @@
 %22 + USER
-NAME
 ;%0A      
@@ -3834,20 +3834,16 @@
 als(USER
-NAME
 , profil
@@ -4165,20 +4165,16 @@
 als(USER
-NAME
 , casPro
@@ -4507,16 +4507,20 @@
 id: 
-username
+%22 + USER + %22
  %7C a
@@ -4601,22 +4601,12 @@
 d: (
-404) Not Found
+500)
 %22);%0A

fix CasRestClientIT