/*
 * 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.service.challenge;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.slf4j.Logger;

import com.scytl.products.oscore.logging.api.domain.Level;
import com.scytl.products.oscore.logging.api.domain.LogContent;
import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.ov.au.services.domain.model.challenge.ChallengeInformation;
import com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogConstants;
import com.scytl.products.ov.au.services.infrastructure.log.AuthenticationLogEvents;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;

/**
 * Tests of {@link ChallengeInformationCredentialIdValidation}.
 */
public class ChallengeInformationCredentialIdValidationTest {
    private static final String TENANT_ID = "tenantId";

    private static final String ELECTION_ID = "electionId";

    private static final String CREDENTIAL_ID = "credentialId";

    private static final String TRACK_ID = "trackId";

    private Logger logger;

    private SecureLoggingWriter secureLoggerWriter;

    private ChallengeInformationCredentialIdValidation validation;

    @Before
    public void setUp() {
        logger = mock(Logger.class);
        secureLoggerWriter = mock(SecureLoggingWriter.class);
        TrackIdInstance trackId = new TrackIdInstance();
        trackId.setTrackId(TRACK_ID);
        validation = new ChallengeInformationCredentialIdValidation(logger,
            secureLoggerWriter, trackId);
    }

    @Test
    public void testExecute()
            throws ResourceNotFoundException{
        ChallengeInformation information = new ChallengeInformation();
        information.setCredentialId(CREDENTIAL_ID);
        assertTrue(validation.execute(TENANT_ID, ELECTION_ID,
            CREDENTIAL_ID, information));
        verify(logger).info(any(String.class), eq(TENANT_ID),
            eq(ELECTION_ID), eq(CREDENTIAL_ID));
    }

    @Test
    public void testExecuteInvalid()
            throws ResourceNotFoundException{
        ChallengeInformation information = new ChallengeInformation();
        information.setCredentialId(CREDENTIAL_ID + "Corrupted");
        assertFalse(validation.execute(TENANT_ID, ELECTION_ID,
            CREDENTIAL_ID, information));
        verify(logger).info(any(String.class), eq(TENANT_ID),
            eq(ELECTION_ID), eq(CREDENTIAL_ID),
            eq(information.getCredentialId()));
        verify(secureLoggerWriter).log(eq(Level.ERROR),
            argThat(new ArgumentMatcher<LogContent>() {
                @Override
                public boolean matches(final Object argument) {
                    return matchesInvalidCredentialIdLogContent(argument,
                        information);
                }
            }));
    }

    private boolean matchesInvalidCredentialIdLogContent(
            final Object argument,
            final ChallengeInformation information) {
        LogContent content = (LogContent) argument;
        Map<String, String> info = content.getAdditionalInfo();
        String trackId =
            info.get(AuthenticationLogConstants.INFO_TRACK_ID);
        String description =
            info.get(AuthenticationLogConstants.INFO_ERR_DESC);
        return AuthenticationLogEvents.CLIENT_CHALLENGE_CID_INVALID
            .equals(content.getLogEvent())
            && CREDENTIAL_ID.equals(content.getObjectId())
            && CREDENTIAL_ID.equals(content.getUser())
            && ELECTION_ID.equals(content.getElectionEvent())
            && TRACK_ID.equals(trackId)
            && description.contains(information.getCredentialId());
    }
}
