/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.au.services.domain.model.authentication;

import com.scytl.products.ov.au.services.domain.service.exception.AuthenticationTokenGenerationException;
import com.scytl.products.ov.au.services.domain.service.exception.AuthenticationTokenSigningException;
import com.scytl.products.ov.commons.beans.validation.ValidationErrorType;
import com.scytl.products.ov.commons.validation.ValidationError;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.slf4j.Logger;

import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.ov.au.services.infrastructure.log.SecureLoggerHelper;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class AuthenticationTokenFactoryDecoratorTest {

    public static final String VOTING_CARD_ID = "100";

    public static final String ELECTION_EVENT_ID = "100";

    public static final String TENANT_ID = "100";
    public static final String TOKEN_HASH = "tokenHash";
    public static final String ID = "100";

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this.getClass());
    }

    @InjectMocks
    private AuthenticationTokenFactoryDecorator decorator = new AuthenticationTokenFactoryDecorator();

    @Mock
    private AuthenticationTokenFactory authenticationTokenFactory;

    @Mock
    private TrackIdInstance trackId;

    @Mock
    private SecureLoggingWriter secureLoggerWriter;

    @Mock
    private SecureLoggerHelper secureLoggerHelper;

    @Mock
    private AuthenticationTokenMessage authenticationTokenMessage;

    @Mock
    private ValidationError validationErrorMock;

    @Mock
    private Logger LOG;

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void buildAuthenticationToken()
            throws AuthenticationTokenGenerationException, AuthenticationTokenSigningException {

        when(authenticationTokenFactory.buildAuthenticationToken(anyString(), anyString(), anyString()))
            .thenReturn(authenticationTokenMessage);
        final AuthenticationTokenMessage authenticationTokenMessage =
            decorator.buildAuthenticationToken(TENANT_ID, ELECTION_EVENT_ID, VOTING_CARD_ID);
        assertNotNull(authenticationTokenMessage);
    }

    @Test
    public void buildAuthenticationTokenGenerationException()
            throws AuthenticationTokenGenerationException, AuthenticationTokenSigningException {

        expectedException.expect(AuthenticationTokenGenerationException.class);
        when(authenticationTokenFactory.buildAuthenticationToken(anyString(), anyString(), anyString()))
            .thenThrow(new AuthenticationTokenGenerationException("exception", null));

        decorator.buildAuthenticationToken(TENANT_ID, ELECTION_EVENT_ID, VOTING_CARD_ID);

    }

    @Test
    public void buildAuthenticationTokenErrorNull()
            throws AuthenticationTokenGenerationException, AuthenticationTokenSigningException {


        when(authenticationTokenFactory.buildAuthenticationToken(anyString(), anyString(), anyString()))
                .thenReturn(authenticationTokenMessage);
        when(authenticationTokenMessage.getValidationError()).thenReturn(null);
        when(secureLoggerHelper.getAuthTokenHash(any())).thenReturn(TOKEN_HASH);
        when(secureLoggerHelper.getAuthTokenId(any())).thenReturn(ID);


        decorator.buildAuthenticationToken(TENANT_ID, ELECTION_EVENT_ID, VOTING_CARD_ID);

    }

    @Test
    public void buildAuthenticationTokenWithKnownError()
            throws AuthenticationTokenGenerationException, AuthenticationTokenSigningException {


        final String[] errors = {""};
        when(authenticationTokenFactory.buildAuthenticationToken(anyString(), anyString(), anyString()))
                .thenReturn(authenticationTokenMessage);
        when(authenticationTokenMessage.getValidationError()).thenReturn(validationErrorMock);
        when(validationErrorMock.getValidationErrorType()).thenReturn(ValidationErrorType.ELECTION_NOT_STARTED);

        when(validationErrorMock.getErrorArgs()).thenReturn(errors);
        when(secureLoggerHelper.getAuthTokenHash(any())).thenReturn(TOKEN_HASH);
        when(secureLoggerHelper.getAuthTokenId(any())).thenReturn(ID);


        decorator.buildAuthenticationToken(TENANT_ID, ELECTION_EVENT_ID, VOTING_CARD_ID);

    }

    @Test
    public void buildAuthenticationTokenWithSuccess()
            throws AuthenticationTokenGenerationException, AuthenticationTokenSigningException {


        when(authenticationTokenFactory.buildAuthenticationToken(anyString(), anyString(), anyString()))
                .thenReturn(authenticationTokenMessage);
        when(authenticationTokenMessage.getValidationError()).thenReturn(validationErrorMock);
        when(validationErrorMock.getValidationErrorType()).thenReturn(ValidationErrorType.SUCCESS);
        when(secureLoggerHelper.getAuthTokenHash(any())).thenReturn(TOKEN_HASH);
        when(secureLoggerHelper.getAuthTokenId(any())).thenReturn(ID);


        decorator.buildAuthenticationToken(TENANT_ID, ELECTION_EVENT_ID, VOTING_CARD_ID);

    }

}
