package com.workfusion.odf.impl.processor;

import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;

import groovy.lang.Binding;
import org.codejargon.feather.Provides;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import com.workfusion.odf.api.domain.Document;
import com.workfusion.odf.api.domain.Transaction;
import com.workfusion.odf.core.Intake;
import com.workfusion.odf.core.Module;
import com.workfusion.odf.service.TransactionService;
import com.workfusion.odf.service.serialization.BusinessProcessFormats;
import com.workfusion.rpa.core.storage.S3Manager;

public class TransactionImporterExport {
    @Inject
    private TransactionImporter importer;

    private S3Manager s3Manager;

    private TransactionService transactionService;

    private Binding binding;


    private Module testModule = new Module(){
        @Provides
        public S3Manager s3Manager() {
            return s3Manager;
        }

        @Provides
        public Binding binding() {
            return binding;
        }

        @Provides
        public TransactionService transactionService() {
            return transactionService;
        }
    };

    @BeforeEach
    public void init() {
        s3Manager = Mockito.mock(S3Manager.class);
        transactionService = Mockito.mock(TransactionService.class);
        binding = Mockito.mock(Binding.class);

        Intake.init(binding).override(testModule).injectFields(this).get();
    }

    @Test
    public void importTransactionWithSameLinks() {
        String transactionId = "123";
        Transaction transactionSafeCopy = buildTransactionWithStaticLinks();

        Transaction transactionToImport = buildTransactionWithStaticLinks();
        String json = BusinessProcessFormats.toJson(transactionToImport);
        Transaction transaction = BusinessProcessFormats.fromJson(json);
        Transaction importedTransaction = importer.transform(transaction);
        Assertions.assertTrue(transactionSafeCopy.equals(importedTransaction));
    }

    @Test
    public void importTransactionWithNullAndEmptyLinks() {
        String transactionId = "123";
        Transaction transactionSafeCopy = buildTransactionWithStaticLinks();
        setEmptyAndNullLinks(transactionSafeCopy);
        Transaction transactionToImport = buildTransactionWithStaticLinks();
        setEmptyAndNullLinks(transactionToImport);
        String json = BusinessProcessFormats.toJson(transactionToImport);
        Transaction transaction = BusinessProcessFormats.fromJson(json);
        Transaction importedTransaction = importer.transform(transaction);
        Assertions.assertTrue(transactionSafeCopy.equals(importedTransaction));
    }

    private void setEmptyAndNullLinks(Transaction transactionToImport) {
        transactionToImport.getDocs().get(0).setTextLink(null);
        transactionToImport.getDocs().get(0).setTaggedTextLink(null);
        transactionToImport.getDocs().get(0).setOriginalDocumentLink(null);
        transactionToImport.getDocs().get(1).setTextLink("");
        transactionToImport.getDocs().get(1).setTaggedTextLink("");
        transactionToImport.getDocs().get(1).setOriginalDocumentLink("");
    }

    @Test
    public void importTransactionWithContent() {
        String generatedS3link = "http://111.12.12.12/generated.html";
        Mockito.when(s3Manager.putFile(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(generatedS3link);

        Transaction transactionSafeCopy = buildTransactionWithSomeContentLinks();

        Transaction transaction = buildTransactionWithSomeContentLinks();

        Transaction importedTransaction = importer.transform(transaction);
        Assertions.assertFalse(transactionSafeCopy.equals(importedTransaction));
        Mockito.verify(s3Manager, Mockito.times(2)).putFile(Mockito.any(), Mockito.any(), Mockito.any());
        Assertions.assertEquals(generatedS3link, importedTransaction.getDocs().get(0).getTextLink());
        Assertions.assertEquals(generatedS3link, importedTransaction.getDocs().get(1).getTaggedTextLink());
        Assertions.assertEquals(transactionSafeCopy.getDocs().get(0).getTaggedTextLink(), transactionSafeCopy.getDocs().get(0).getTaggedTextLink());
        Assertions.assertEquals(transactionSafeCopy.getDocs().get(1).getTextLink(), transactionSafeCopy.getDocs().get(1).getTextLink());
        Assertions.assertEquals(generatedS3link, importedTransaction.getDocs().get(1).getTaggedTextLink());
    }

    private Transaction buildTransactionWithSomeContentLinks() {
        Transaction transaction = buildTransactionWithStaticLinks();
        transaction.getDocs().get(0).setTextLink("<html></html>");
        transaction.getDocs().get(1).setTaggedTextLink("<html><title/></html>");

        return transaction;
    }

    private Transaction buildTransactionWithStaticLinks() {
        final Transaction transaction = new Transaction();
        transaction.setId("1");
        final List<Document> docs = new ArrayList<>();

        Document doc = new Document();
        doc.setId("1");
        doc.setName("name1");
        doc.setType("type1");
        doc.setTextLink("http://111.12.12.12/link1.html");
        doc.setTaggedTextLink("http://111.12.12.12/link1_tagged.html");
        doc.setOriginalDocumentLink("http://111.12.12.12/link1.xlsx");
        docs.add(doc);

        Document doc1 = new Document();
        doc1.setId("2");
        doc1.setName("name2");
        doc1.setType("type1");
        doc1.setTextLink("http://111.12.12.12/link2.html");
        doc1.setTaggedTextLink("http://111.12.12.12/link2_tagged.html");
        doc1.setOriginalDocumentLink("http://111.12.12.12/link2.xlsx");
        docs.add(doc1);

        transaction.setDocs(docs);

        return transaction;
    }
}
