/*
 * 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.vv.domain.model.rule;

import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.slf4j.Logger;

import com.scytl.cryptolib.api.asymmetric.AsymmetricServiceAPI;
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
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.validation.ValidationError;
import com.scytl.products.ov.vv.domain.model.verificationset.VerificationSetEntity;
import com.scytl.products.ov.vv.domain.model.verificationset.VerificationSetRepository;

/**
 *
 */
@RunWith(MockitoJUnitRunner.class)
public class VerifyVerificationCardPKSignatureRuleTest {

    @InjectMocks
    private VerifyVerificationCardPKSignatureRule verifyVerificationCardPKSignatureRule =
        new VerifyVerificationCardPKSignatureRule();

    @Mock
    private VerificationSetRepository verificationSetRepository;

    @Mock
    private AsymmetricServiceAPI asymmetricService;

    @Mock
    private Logger LOG;

    private String verificationCardPublicKey =
        "eyJwdWJsaWNLZXkiOnsienBTdWJncm91cCI6eyJwIjoiMTYzNzA1MTg5OTQzMTk1ODY3NjAzMTk3OTE1MjYyOTM1MzUzMjc1NzY0Mzg2NDY3ODIxMzk0MTk4NDYwMDQxODA4MzcxMDM1MjcxMjkwMzU5NTQ3NDIwNDM1OTA2MDk0MjEzNjk2NjU5NDQ3NDY1ODc4ODU4MTQ5MjA4NTE2OTQ1NDY0NTY4OTE3Njc2NDQ5NDU0NTkxMjQ0MjI1NTM3NjM0MTY1ODY1MTUzMzk5NzgwMTQxNTQ0NTIxNTk2ODcxMDkxNjEwOTA2MzUzNjc2MDAzNDkyNjQ5MzQ5MjQxNDE3NDYwODIwNjAzNTM0ODMzMDY4NTUzNTIxOTIzNTg3MzI0NTE5NTUyMzIwMDA1OTM3Nzc1NTQ0MzE3OTg5ODE1NzQ1Mjk4NTQzMTQ2NTEwOTIwODY0ODg0MjYzOTA3NzY4MTEzNjcxMjUwMDk1NTEzNDYwODkzMTkzMTUxMTE1MDkyNzczNDcxMTc0NjcxMDc5MTQwNzM2Mzk0NTY4MDUxNTkwOTQ1NjI1OTM5NTQxOTU5NjA1MzExMzYwNTIyMDgwMTkzNDMzOTI5MDY4MTYwMDEwMTc0ODgwNTEzNjY1MTgxMjI0MDQ4MTk5NjcyMDQ2MDE0MjczMDQyNjczODAyMzgyNjM5MTM4OTI2NTg5NTAyODE1OTM3NTU4OTQ3NDczMzkxMjY1MzEwMTgwMjY3OTg5ODI3ODUzMzEwNzkwNjUxMjYzNzU0NTUyOTM0MDkwNjU1NDA3MzE2NDY5Mzk4MDg2NDAyNzMzOTM4NTUyNTYyMzA4MjA1MDkyMTc0MTE1MTAwNTg3NTkiLCJxIjoiODE4NTI1OTQ5NzE1OTc5MzM4MDE1OTg5NTc2MzE0Njc2NzY2Mzc4ODIxOTMyMzM5MTA2OTcwOTkyMzAwMjA5MDQxODU1MTc2MzU2NDUxNzk3NzM3MTAyMTc5NTMwNDcxMDY4NDgzMjk3MjM3MzI5Mzk0MjkwNzQ2MDQyNTg0NzI3MzIyODQ0NTg4MzgyMjQ3MjcyOTU2MjIxMTI3Njg4MTcwODI5MzI1NzY2OTk4OTAwNzA3NzIyNjA3OTg0MzU1NDU4MDU0NTMxNzY4MzgwMDE3NDYzMjQ2NzQ2MjA3MDg3MzA0MTAzMDE3Njc0MTY1MzQyNzY3NjA5NjE3OTM2NjIyNTk3NzYxNjAwMDI5Njg4ODc3NzIxNTg5OTQ5MDc4NzI2NDkyNzE1NzMyNTU0NjA0MzI0NDIxMzE5NTM4ODQwNTY4MzU2MjUwNDc3NTY3MzA0NDY1OTY1NzU1NTc1NDYzODY3MzU1ODczMzU1Mzk1NzAzNjgxOTcyODQwMjU3OTU0NzI4MTI5Njk3NzA5Nzk4MDI2NTU2ODAyNjEwNDAwOTY3MTY5NjQ1MzQwODAwMDUwODc0NDAyNTY4MzI1OTA2MTIwMjQwOTk4MzYwMjMwMDcxMzY1MjEzMzY5MDExOTEzMTk1Njk0NjMyOTQ3NTE0MDc5Njg3Nzk0NzM3MzY2OTU2MzI2NTUwOTAxMzM5OTQ5MTM5MjY2NTUzOTUzMjU2MzE4NzcyNzY0NjcwNDUzMjc3MDM2NTgyMzQ2OTkwNDMyMDEzNjY5NjkyNzYyODExNTQxMDI1NDYwODcwNTc1NTAyOTM3OSIsImciOiIyIn0sImVsZW1lbnRzIjpbIjg3NTc1MTg4NjUxODMyMzk0NzA3MDk1NDI0MDEwNDcyODU2MzIyODYwMDYyNTM0Njc3ODI4ODAyMjA2NzQ0NTIzNDg0MDA2MzgzNTUwMDE4NzIyNjQzNzkzOTY2MzYyNzkwNDk0NzI5MjkyMTU1Njc4NTIzNDM4NDkwNTAzOTI5NTcyODY5OTA3ODY5NzM4MzMwODM3MDM5NTM3MjgwNTg3ODc0MDA3Mzc3OTgxMTIzMDk3OTE2NjMxOTU0ODMyNTI1MjQ4NjY5OTAzMjQwODQzMzA1Mzg1OTE1OTg3NDU4OTEzMTkyNjUyODEzNTM5MDQxMzM2ODkzMzE2ODM0ODEyNTAyMjg1MTgwMTMyNzQ5Nzc4MTc2Mzk2NDU5Mjg3Mjg0MTU4NTAwMjUxNzIyMjkxNzY0MDQzNTg3NzcyMDUxNDQ2NjU0MTM2ODE1MDI5NDc2MDk1MDAwMzMzODk3OTg2NTUyOTgzNzI4OTM5ODA3MjMwOTk5NDE2MzI1ODkxMTA3MDkzNjc5ODk5MjgyOTk3Nzc3ODEzNjUyNzcyMDY1OTg5ODU5OTQ3ODMzNDQwMjY0OTk0MTA4ODcxMTk2NDI0NjQ0MzY3OTY4OTkxOTEyOTU1MTM3OTM5NzA0ODA1NzM2NjgxMzY1MTgyNzUyMzAwOTE3OTM2NDI5MzA0MDA4OTY1NTIzOTE5NzI1MTY5MTQ0OTkxMjEzMTkzMzE3Mjc4OTQ5MTQ5OTc3MTI3MzE3MDEwNjgyOTQxMjE5ODQ1ODQ0MTk4MjM5ODA5NzI2MjE0MTcxNTgxMzE0NDQ2MjYzMjg4NDY0MjEiXX19";

    private String verificationCardPKSignature =
        "OZY7wYTLmeWNhp/xAwTZPO8HKu4giRxB5y1Q9jlVvZNH2BmjQOQbz38D5bMUZbj8ILE04tKzNelEMa5vJdDTaQAzsnRxc295HTvWGTH0sPd6brXK2QPVoJeoXQBz0b2RETgFsC/Goya5qMwZ3aRfH7FSKghnXlFHEM6EY+F3GacvftppQfgHMTcC7ABGAeE5IuikL3SlqsKvhnF7UTtwc8YSnuHpQGSNhfEed9G+fn4Tws6x/AQHjcwsT3Ryq02L0b598g7XJjyXdlbvLQ7OY1M1x1iRRzIkrC4yn6dqTfzc1bw1beDxfhHKqDGb3MKsR8O90PAAHsaVCJFWKJOJGg==";

    private String verificationDataSetInvalidJson =
        "{\"voteCastCodeSignerCert\":\"-----BEGIN CERTIFICATE-----\nMIIDrDCCApSgAwIBAgIUA9WGUh0TKSDItJtk4gnTa5cTp+4wDQYJKoZIhvcNAQEL\nBQAwezE1MDMGA1UEAwwsU2VydmljZXMgQ0EgMWQ5NDJkMmY3ZWUyNDE1MGFmNmFi\nOTc5ZDNjNDNjNTkxFjAUBgNVBAsMDU9ubGluZSBWb3RpbmcxEjAQBgNVBAoMCVN3\naXNzUG9zdDEJMAcGA1UEBwwAMQswCQYDVQQGEwJDSDAeFw0xNTEyMjIxNDA3MzRa\nFw0xNjEyMTAxMDAwMDBaMIGCMTwwOgYDVQQDDDNWb3RlQ2FzdENvZGVTaWduZXIg\nMWQ5NDJkMmY3ZWUyNDE1MGFmNmFiOTc5ZDNjNDNjNTkxFjAUBgNVBAsMDU9ubGlu\nZSBWb3RpbmcxEjAQBgNVBAoMCVN3aXNzUG9zdDEJMAcGA1UEBwwAMQswCQYDVQQG\nEwJDSDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJtZIbu1KnoYZ7xG\nZwbNa0oTayR4f2PfQBUb+8s48y9bCnLfVyuYcq5K7uGJkUHEafPtD37jJkPYr+de\nF6CXHtB9sypJo2OAHn/qT2BYU4axqUOnzSGyGTCYkB7j1YvO8HEc6BvmgiBmjGKN\nVibeWqwqXID2rxOsbfBv32Z3VNBmPoIGac6Tr+F48x3Ov0TSRr5UYYv5NzhlJczQ\nU60RCWtgnuqeLOJcsVgN3jLlpWAby4Jd6bZh+t0Ut07dqLFj4n3lL6D+jVh7qeLJ\n9cfnGABYNe9JD7K1EuaXkELojlGSTtfjFkCyywseIWAIRJkiPhK6dPjpHoZXHljt\nG443MnsCAwEAAaMgMB4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBsAwDQYJ\nKoZIhvcNAQELBQADggEBAA7MMAl0wxvHY+dZizlFq7A548IcZFdGtB/GQG0NGO6V\nQAOixk+se2IsQV1R0AuxBbKC+r93D4/zJ+1THQIujz1dSGFcdXXkast/nbMl+HFg\nM4QpMBCH6Zv455STUbnrZD7t2MgheIFTjh3iiu+txsF24Phg+osQjHYmq6oP8muH\ndbM/S59shdyFpX6zGR03EZhNtHAYlhaj3CdZPL/yxZtfH5NZvEBcpL68oIvw2ZPH\ndt3mRoicqQ57iaSL5+QUyTzZmWCKqSzeczb9z+QDOKMLx/muDjumGViOQQGTRg/e\nbOhSoeZHjSKShSTfWk8E14I/VQrK0QRwMB1+ANMQTzA=\n-----END CERTIFICATE-----\n\",\"electionEventId\":\"1d942d2f7ee24150af6ab979d3c43c59\",\"verificationCardIssuerCert\":\"-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIVAPc+RhmguzzCd2/+axuAjpGAWpbJMA0GCSqGSIb3DQEB\nCwUAMHsxNTAzBgNVBAMMLFNlcnZpY2VzIENBIDFkOTQyZDJmN2VlMjQxNTBhZjZh\nYjk3OWQzYzQzYzU5MRYwFAYDVQQLDA1PbmxpbmUgVm90aW5nMRIwEAYDVQQKDAlT\nd2lzc1Bvc3QxCTAHBgNVBAcMADELMAkGA1UEBhMCQ0gwHhcNMTUxMjIyMTQwNzM0\nWhcNMTYxMjEwMTAwMDAwWjCBhjFAMD4GA1UEAww3VmVyaWZpY2F0aW9uQ2FyZElz\nc3VlciAxZDk0MmQyZjdlZTI0MTUwYWY2YWI5NzlkM2M0M2M1OTEWMBQGA1UECwwN\nT25saW5lIFZvdGluZzESMBAGA1UECgwJU3dpc3NQb3N0MQkwBwYDVQQHDAAxCzAJ\nBgNVBAYTAkNIMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhQj73Ozc\nC9YlUVElc9YnowOpTr7ekHNeWNZQIhWIQojfJTMuhGl9ZZx4rFk7LPVMMdt0Nt/6\nQ70RIhKb3XPpe4j6pO+rLS1xQsdRvFwydZivgM2A3qKNIiRjtJqRE6jyTHasaQ2G\nX5RVcjFGJ+Rt2shvMP+bUqmbege6ukGXRbDKFwm7v6IBTqnd06o2WwsbMB+jGPW1\nCJP6bwQv3pPwGiZbrYE9Onft5XbsqYqkf1r1PQnPzQmIsRg1Q7GFSgGy0g/F9FkH\ndZbN5tBeT3DFywg1BRUNNYcx07nXJ3kJSB6UUzA5+x1lQRTp8gnEbxPd1iH4hWns\nQda6TrvnqD9WAQIDAQABoyAwHjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIG\nwDANBgkqhkiG9w0BAQsFAAOCAQEAbhyR3xy7ZRE20y4u60XbJVDET4NbEcLQejkn\nzqdZ5ebUELvwDgs+JwaHJQfQ5yjxVb4dilR3Eq//nWCRQ30iLFvFSzZ94xtFRVFA\nH9hw2MDGFVLUprP6wFEpptQoYy8/sVRWxQcOjWmM7TSyg53ljzTZVceEp09++mf3\n1NsAveU/UquAIUvwDm+Qw+U64ClGMpJqFqMebJ+Fomry3yaIxCI4ToGgcw22c8E3\nrJ9nowpJzK4BahRfIOxHe/YtF6/97HUXbQ3z+JztvNT0nrz/wsPrgTQ4eblPQjH1\n9QJxxKQoPJWUqvnSbaH26vb4ctms4Ihh8quh39TaiWjp6LHymw==\n-----END CERTIFICATE-----\n\",\"verificationCardSetId\":\"4e84749ff7a64f1cbb97a4ca26fb9298\",\"choicesCodesEncryptionPublicKey\":\"[encoded data, 14124 characters]\"}";

    private String verificationDataSetJson =
        "{\"electionEventId\":\"1d942d2f7ee24150af6ab979d3c43c59\",\"verificationCardIssuerCert\":\"-----BEGIN CERTIFICATE-----\\r\\nMIIDsTCCApmgAwIBAgIVAPc+RhmguzzCd2/+axuAjpGAWpbJMA0GCSqGSIb3DQEB\\r\\nCwUAMHsxNTAzBgNVBAMMLFNlcnZpY2VzIENBIDFkOTQyZDJmN2VlMjQxNTBhZjZh\\r\\nYjk3OWQzYzQzYzU5MRYwFAYDVQQLDA1PbmxpbmUgVm90aW5nMRIwEAYDVQQKDAlT\\r\\nd2lzc1Bvc3QxCTAHBgNVBAcMADELMAkGA1UEBhMCQ0gwHhcNMTUxMjIyMTQwNzM0\\r\\nWhcNMTYxMjEwMTAwMDAwWjCBhjFAMD4GA1UEAww3VmVyaWZpY2F0aW9uQ2FyZElz\\r\\nc3VlciAxZDk0MmQyZjdlZTI0MTUwYWY2YWI5NzlkM2M0M2M1OTEWMBQGA1UECwwN\\r\\nT25saW5lIFZvdGluZzESMBAGA1UECgwJU3dpc3NQb3N0MQkwBwYDVQQHDAAxCzAJ\\r\\nBgNVBAYTAkNIMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhQj73Ozc\\r\\nC9YlUVElc9YnowOpTr7ekHNeWNZQIhWIQojfJTMuhGl9ZZx4rFk7LPVMMdt0Nt/6\\r\\nQ70RIhKb3XPpe4j6pO+rLS1xQsdRvFwydZivgM2A3qKNIiRjtJqRE6jyTHasaQ2G\\r\\nX5RVcjFGJ+Rt2shvMP+bUqmbege6ukGXRbDKFwm7v6IBTqnd06o2WwsbMB+jGPW1\\r\\nCJP6bwQv3pPwGiZbrYE9Onft5XbsqYqkf1r1PQnPzQmIsRg1Q7GFSgGy0g/F9FkH\\r\\ndZbN5tBeT3DFywg1BRUNNYcx07nXJ3kJSB6UUzA5+x1lQRTp8gnEbxPd1iH4hWns\\r\\nQda6TrvnqD9WAQIDAQABoyAwHjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIG\\r\\nwDANBgkqhkiG9w0BAQsFAAOCAQEAbhyR3xy7ZRE20y4u60XbJVDET4NbEcLQejkn\\r\\nzqdZ5ebUELvwDgs+JwaHJQfQ5yjxVb4dilR3Eq//nWCRQ30iLFvFSzZ94xtFRVFA\\r\\nH9hw2MDGFVLUprP6wFEpptQoYy8/sVRWxQcOjWmM7TSyg53ljzTZVceEp09++mf3\\r\\n1NsAveU/UquAIUvwDm+Qw+U64ClGMpJqFqMebJ+Fomry3yaIxCI4ToGgcw22c8E3\\r\\nrJ9nowpJzK4BahRfIOxHe/YtF6/97HUXbQ3z+JztvNT0nrz/wsPrgTQ4eblPQjH1\\r\\n9QJxxKQoPJWUqvnSbaH26vb4ctms4Ihh8quh39TaiWjp6LHymw==\\r\\n-----END CERTIFICATE-----\\r\\n\",\"verificationCardSetId\":\"4e84749ff7a64f1cbb97a4ca26fb9298\"}";

    @Test
    public void verificationJsonValid() throws ResourceNotFoundException, GeneralCryptoLibException {
        Vote vote = new Vote();
        vote.setTenantId("100");
        vote.setElectionEventId("100");
        vote.setVotingCardId("100");
        vote.setVerificationCardId("100");
        vote.setVerificationCardSetId("100");
        vote.setVerificationCardPublicKey(verificationCardPublicKey);
        vote.setVerificationCardPKSignature(verificationCardPKSignature);

        VerificationSetEntity verificationDataSet = new VerificationSetEntity();
        verificationDataSet.setJSON(verificationDataSetJson);
        when(verificationSetRepository.findByTenantIdElectionEventIdVerificationCardSetId(anyString(), anyString(),
            anyString())).thenReturn(verificationDataSet);

        when(asymmetricService.verifySignature(any(), any(), any(), any(), any())).thenReturn(true);

        ValidationError result = verifyVerificationCardPKSignatureRule.execute(vote);

        assertTrue(result.getValidationErrorType().equals(ValidationErrorType.SUCCESS));
    }

    @Test
    public void verificationJsonParsingError() throws ResourceNotFoundException {
        Vote vote = new Vote();
        vote.setTenantId("100");
        vote.setElectionEventId("100");
        vote.setVotingCardId("100");
        vote.setVerificationCardId("100");
        vote.setVerificationCardSetId("100");
        vote.setVerificationCardPublicKey(verificationCardPublicKey);
        vote.setVerificationCardPKSignature(verificationCardPKSignature);

        VerificationSetEntity verificationDataSet = new VerificationSetEntity();
        verificationDataSet.setJSON(verificationDataSetInvalidJson);
        when(verificationSetRepository.findByTenantIdElectionEventIdVerificationCardSetId(anyString(), anyString(),
            anyString())).thenReturn(verificationDataSet);

        ValidationError result = verifyVerificationCardPKSignatureRule.execute(vote);

        assertTrue(result.getValidationErrorType().equals(ValidationErrorType.FAILED));
    }

    @Test
    public void verificationJsonNotValid() throws ResourceNotFoundException, GeneralCryptoLibException {
        Vote vote = new Vote();
        vote.setTenantId("100");
        vote.setElectionEventId("100");
        vote.setVotingCardId("100");
        vote.setVerificationCardId("100");
        vote.setVerificationCardSetId("100");
        vote.setVerificationCardPublicKey(verificationCardPublicKey);
        vote.setVerificationCardPKSignature(verificationCardPKSignature);

        VerificationSetEntity verificationDataSet = new VerificationSetEntity();
        verificationDataSet.setJSON(verificationDataSetJson);
        when(verificationSetRepository.findByTenantIdElectionEventIdVerificationCardSetId(anyString(), anyString(),
            anyString())).thenReturn(verificationDataSet);

        when(asymmetricService.verifySignature(any(), any(), any(), any(), any())).thenReturn(false);

        ValidationError result = verifyVerificationCardPKSignatureRule.execute(vote);

        assertTrue(result.getValidationErrorType().equals(ValidationErrorType.FAILED));
    }

}
