/*
 * 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.vw.services.infrastructure.remote;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.BeforeClass;
import org.junit.Test;
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.commons.beans.domain.model.vote.Vote;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.beans.validation.ValidationErrorType;
import com.scytl.products.ov.commons.tracking.TrackIdInstance;
import com.scytl.products.ov.commons.validation.ValidationError;
import com.scytl.products.ov.commons.validation.ValidationResult;
import com.scytl.products.ov.vw.infrastructure.log.SecureLoggerInformation;
import com.scytl.products.ov.vw.services.domain.model.validation.ValidationRepository;
import com.scytl.products.ov.vw.services.domain.model.vote.ValidationVoteResult;

import com.scytl.products.ov.commons.infrastructure.remote.client.RetrofitException;
import okhttp3.ResponseBody;

@RunWith(MockitoJUnitRunner.class)
public class ValidationRepositoryDecoratorTest {

	@Mock
	private ValidationRepository validationRepository;

	@Mock
	private TrackIdInstance trackId;

	@Mock
	private SecureLoggingWriter secureLoggerWriter;

	@Mock
	private SecureLoggerInformation secureLoggerInformation;

	@Mock
	private Logger LOG;
	
	@InjectMocks
	ValidationRepositoryDecorator rut = new ValidationRepositoryDecorator() { };
	
	@BeforeClass
	public static void setup() 	{
		MockitoAnnotations.initMocks(ValidationRepositoryDecoratorTest.class);
	    Security.addProvider(new BouncyCastleProvider());
	}

	@Test
	public void testValidateElectionDatesInEISuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		String ballotBoxId = "1";
		
		ValidationResult validationResultMock = new ValidationResult();
		validationResultMock.setResult(true);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateElectionDatesInEI(tenantId, electionEventId, ballotBoxId)).thenReturn(validationResultMock);
		ValidationResult validationResult = rut.validateElectionDatesInEI(tenantId, electionEventId, ballotBoxId);
		
		assertEquals(validationResultMock.isResult(), validationResult.isResult());
	}
	
	@Test
	public void testValidateElectionDatesInEIResultFalseSuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		String ballotBoxId = "1";
		
		ValidationResult validationResultMock = new ValidationResult();
		validationResultMock.setResult(false);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateElectionDatesInEI(tenantId, electionEventId, ballotBoxId)).thenReturn(validationResultMock);
		ValidationResult validationResult = rut.validateElectionDatesInEI(tenantId, electionEventId, ballotBoxId);
		
		assertEquals(validationResultMock.isResult(), validationResult.isResult());
	}
	
	@Test(expected=ResourceNotFoundException.class)
	public void testValidateElectionDatesInEIResultNotFoundException() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		String ballotBoxId = "1";
		
		when(validationRepository.validateElectionDatesInEI(tenantId, electionEventId, ballotBoxId)).thenThrow(new ResourceNotFoundException("exception"));
		rut.validateElectionDatesInEI(tenantId, electionEventId, ballotBoxId);
	}
	
	@Test
	public void testValidateVoteInVVSuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		ValidationResult validationResultMock = new ValidationResult();
		validationResultMock.setResult(true);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateVoteInVV(tenantId, electionEventId, voteMock)).thenReturn(validationResultMock);
		ValidationResult validationResult = rut.validateVoteInVV(tenantId, electionEventId, voteMock);
		
		assertEquals(validationResultMock.isResult(), validationResult.isResult());
	}

	@Test
	public void testValidateVoteInVVResultFalseSuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		ValidationResult validationResultMock = new ValidationResult();
		validationResultMock.setResult(false);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateVoteInVV(tenantId, electionEventId, voteMock)).thenReturn(validationResultMock);
		ValidationResult validationResult = rut.validateVoteInVV(tenantId, electionEventId, voteMock);
		
		assertEquals(validationResultMock.isResult(), validationResult.isResult());
	}
	
	@Test(expected=ResourceNotFoundException.class)
	public void testValidateVoteInVVResultNotFoundException() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		when(validationRepository.validateVoteInVV(tenantId, electionEventId, voteMock)).thenThrow(new ResourceNotFoundException("exception"));
		rut.validateVoteInVV(tenantId, electionEventId, voteMock);
	}
	
	@Test
	public void testValidateVoteInEISuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		ValidationResult validationResultMock = new ValidationResult();
		validationResultMock.setResult(true);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateVoteInEI(tenantId, electionEventId, voteMock)).thenReturn(validationResultMock);
		ValidationResult validationResult = rut.validateVoteInEI(tenantId, electionEventId, voteMock);
		
		assertEquals(validationResultMock.isResult(), validationResult.isResult());
	}

	@Test
	public void testValidateVoteInEIResultFalseSuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		ValidationResult validationResultMock = new ValidationResult();
		validationResultMock.setResult(false);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateVoteInEI(tenantId, electionEventId, voteMock)).thenReturn(validationResultMock);
		ValidationResult validationResult = rut.validateVoteInEI(tenantId, electionEventId, voteMock);
		
		assertEquals(validationResultMock.isResult(), validationResult.isResult());
	}
	
	@Test(expected=ResourceNotFoundException.class)
	public void testValidateVoteInEIResultNotFoundException() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		when(validationRepository.validateVoteInEI(tenantId, electionEventId, voteMock)).thenThrow(new ResourceNotFoundException("exception"));
		rut.validateVoteInEI(tenantId, electionEventId, voteMock);
	}
	
	@Test
	public void testValidateVoteSuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		ValidationVoteResult validationResultMock = new ValidationVoteResult();
		validationResultMock.setValid(true);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateVote(tenantId, electionEventId, voteMock)).thenReturn(validationResultMock);
		ValidationVoteResult validationResult = rut.validateVote(tenantId, electionEventId, voteMock);
		
		assertEquals(validationResultMock.isValid(), validationResult.isValid());
	}

	@Test
	public void testValidateVoteResultFalseSuccessful() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		ValidationVoteResult validationResultMock = new ValidationVoteResult();
		validationResultMock.setValid(false);
		validationResultMock.setValidationError(new ValidationError(ValidationErrorType.SUCCESS));
		
		when(validationRepository.validateVote(tenantId, electionEventId, voteMock)).thenReturn(validationResultMock);
		ValidationVoteResult validationResult = rut.validateVote(tenantId, electionEventId, voteMock);
		
		assertEquals(validationResultMock.isValid(), validationResult.isValid());
	}
	
	@Test(expected=ResourceNotFoundException.class)
	public void testValidateVoteResultNotFoundException() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		int notFoundStatus = 404;
		
		RetrofitException error = new RetrofitException(notFoundStatus, ResponseBody.create(okhttp3.MediaType.parse("text/html"), new byte[0]));
		
		when(validationRepository.validateVote(tenantId, electionEventId, voteMock)).thenThrow(error);
		rut.validateVote(tenantId, electionEventId, voteMock);
	}
	
	@Test
	public void testValidateVoteResultInvalidCausedByError() throws ResourceNotFoundException {
		String tenantId = "100";
		String electionEventId = "1";
		Vote voteMock = new Vote();
		
		int internalServerError = 500;
		
		RetrofitException error = new RetrofitException(internalServerError, ResponseBody.create(okhttp3.MediaType.parse("text/html"), new byte[0]));
		
		when(validationRepository.validateVote(tenantId, electionEventId, voteMock)).thenThrow(error);
		ValidationVoteResult validationResult = rut.validateVote(tenantId, electionEventId, voteMock);
		
		assertEquals(false, validationResult.isValid());
	}
}
