package com.iqser.red.service.peristence.v1.server.integration.tests;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.iqser.red.service.peristence.v1.server.integration.client.ReportTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.ReportTemplateProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.ReportTemplateUpdateRequest;

import feign.FeignException;

public class ReportTemplateTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private ReportTemplateClient reportTemplateClient;

    @Autowired
    private ReportTemplateProvider reportTemplateProvider;


    /*
     * Upload report, verify it exist and delete afterwards
     */
    @Test
    public void testReportTemplate() {

        // Arrange
        String fileName = "report.xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName);

//        var download = reportTemplateClient.downloadReportTemplate(firstTemplate.getDossierTemplateId(), firstTemplate.getTemplateId());
//        assertThat(download.getFile().length).isEqualTo(4);

        reportTemplateClient.deleteTemplate(firstTemplate.getDossierTemplateId(), firstTemplate.getTemplateId());

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

    }


    /*
     * Upload multiFile report, verify it exist with correct fileName and delete afterwards
     */
    @Test
    public void testMultiFileReportTemplate() {

        // Arrange
        String fileName = "report.xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo("report.xlsx");

        reportTemplateClient.deleteTemplate(firstTemplate.getDossierTemplateId(), firstTemplate.getTemplateId());

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

    }


    /*
     * Upload template file and then multi file template with the same name
     */
    @Test
    public void testReportTemplateAndThenMultiFileReportTemple() {

        // Arrange
        String fileName = "report.xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName);

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();
        assertThat(availableTemplates.size()).isEqualTo(2);

        var secondTemplate = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(availableTemplates).contains(secondTemplate);
        assertThat(secondTemplate.getFileName()).isEqualTo("report.xlsx");

    }


    /*
     * Upload multi file template and then template file with the same name
     */
    @Test
    public void testMultiFileReportTemplateAndThenReportTemple() {

        // Arrange
        String fileName = "report.xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo("report.xlsx");

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName, "content".getBytes(), false, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();
        assertThat(availableTemplates.size()).isEqualTo(2);

        var secondTemplate = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(availableTemplates).contains(secondTemplate);
        assertThat(secondTemplate.getFileName()).isEqualTo(fileName);

    }


    /*
     * Upload MF with ending xlsx
     */
    @Test
    public void testMultiFileReportTemplateAsExcel() {
        // Arrange
        String fileName = "report with really_weird~Name(567) [}=§$783 XYz&";
        String fileEnding = ".xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName + fileEnding, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = availableTemplates.iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName + fileEnding);

    }


    /*
     * Upload MF with ending docx
     */
    @Test
    public void testMultiFileReportTemplateAsWord() {
        // Arrange
        String fileName = "report with really_weird~Name(567) [}=§$783 XYz&";
        String fileEnding = ".docx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName + fileEnding, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = availableTemplates.iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName + fileEnding);

    }


    /*
     * Upload multiFile report with fantasy fileEnding
     */
    @Test
    public void testMultiFileReportTemplateWithFantasyName() {
        // Arrange
        String fileName = "report with really_weird~Name(567) [}=§$783 XYz&";
        String fileEnding = ".fantasyEnding";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName + fileEnding, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = availableTemplates.iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName + fileEnding);

    }


    /*
     * Upload multiFile report with fantasy fileEnding
     */
    @Test
    public void testMultiFileReportTemplateWithDotsInName() {
        // Arrange
        String fileName = "awesome.report.with.many.dots";
        String fileEnding = ".xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName + fileEnding, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = availableTemplates.iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName + fileEnding);

    }


    /*
     * Update report
     */
    @Test
    public void testReportTemplateUpdate() {

        // Arrange
        String fileName = "report.xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // Act & Assert
        // Act & Assert
        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isEmpty();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName, "content".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates).isNotEmpty();

        var firstTemplate = availableTemplates.iterator().next();
        assertThat(availableTemplates.iterator().next()).isEqualTo(firstTemplate);
        assertThat(firstTemplate.getFileName()).isEqualTo(fileName);

        String filenameUpdate = "reportUpdated.xlsx";
        var updateRequest = new ReportTemplateUpdateRequest(filenameUpdate, true, true);
        reportTemplateClient.updateTemplate(dossierTemplate.getId(), firstTemplate.getTemplateId(), updateRequest);

        var templateUpdated = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).iterator().next();
        assertThat(templateUpdated.getFileName()).isEqualTo(filenameUpdate);
        assertThat(templateUpdated.isMultiFileReport()).isTrue();
        assertThat(templateUpdated.isActiveByDefault()).isTrue();

        try {
            reportTemplateClient.updateTemplate("123wrongDossier", firstTemplate.getTemplateId(), updateRequest);
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(404);
        }
    }


    @Test
    public void testTemplateOverride() {

        String fileName = "report.xlsx";
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName, "content".getBytes(), true, true);

        var availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        String templateId = availableTemplates.get(0).getTemplateId();

        reportTemplateProvider.provideReportTemplate(dossierTemplate.getDossierTemplateId(), fileName, "content xyz".getBytes(), true, true);

        availableTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
        assertThat(availableTemplates.size()).isEqualTo(1);

    }

}
