package com.capgemini.reports.definition.r25report;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.InvalidConfigurationException;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.framework.teamcenter.exceptions.NoTeamcenterConnectionException;
import com.capgemini.framework.teamcenter.policies.PolicyLocation;
import com.capgemini.reports.builder.R25Builder;
import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum;
import com.capgemini.reports.execution.strategies.ImmediateExecutionStrategy;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.assertj.core.api.SoftAssertions;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


@Slf4j
public class Test_R25 {
  private static final TcSession session = new TcSession();
  private SoftAssertions softAssert = new SoftAssertions();
  private static final String ZIP_INPUT_FOLDER = "com.capgemini.report.location.default.input";
  private static final String TEMPORARY_OUTPUT_FOLDER = "com.capgemini.report.location.default.output";
  private static final String SUFFIX = ".zip";
  private static final PolicyLocation XML_POLICY = PolicyLocation.make("test_policy", "/xml/policies/r25report/R25_policy_full.xml");
  private Properties localproperties;


  @BeforeClass
  public void login() throws NoTeamcenterConnectionException, InvalidConfigurationException, IOException {
    session.login();
    session.setObjectPropPolicy(XML_POLICY);
    localproperties = new Properties();
    localproperties.load(getClass().getResourceAsStream("/reporting.properties"));
  }

  @AfterClass
  public void logout() {
    session.close();
  }


  @Parameters({"productID", "unit", "typeImpression", "language", "refFile"})
  @Test
  public void test25(String productID, @Optional String unit, String typeImpression, String language, String refFile) throws
      KurtException, IOException, ZipException {
    // Génération du rapport de test
    Map<ReportCriteriaEnum, String> data = new HashMap<>();
    data.put(ReportCriteriaEnum.PRODUCT, productID);
    data.put(ReportCriteriaEnum.UNIT, unit);
    data.put(ReportCriteriaEnum.TYPE_IMPRESSION, typeImpression);
    data.put(ReportCriteriaEnum.LANGUAGE, language);

    ExecutionR25 execution = (ExecutionR25) new R25Builder().build(data);
    new DataReportPreparatorR25().print(session, execution, new ImmediateExecutionStrategy());


    ArrayList<XSSFWorkbook> excelListRef = new ArrayList<>();
    ArrayList<XSSFWorkbook> excelListGen = new ArrayList<>();
    Path tempDirZipGenerated = Files.createTempDirectory("tempfilesZipGenerated");
    Path tempDirExcelGenerated = Files.createTempDirectory("tempfilesExcelGenerated");
    Path tempDirExcelReferenced = Files.createTempDirectory("tempfilesExcelReferenced");
    Path tempDirZipReferenced = Files.createTempDirectory("tempfilesZipReferenced");

    DataFormatter df = new DataFormatter();

    // Extraction du Zip parent Fichier Generated
    ZipFile sourceGen2 = new ZipFile(localproperties.getProperty(TEMPORARY_OUTPUT_FOLDER) + execution.getFileNameOnDisc() + SUFFIX);
    sourceGen2.extractAll(tempDirZipGenerated.toString());

    // Extraction des Zips enfants Fichier Generated

    for (File aFileGen : tempDirZipGenerated.toFile().listFiles()) {
      ZipFile sourceGen = new ZipFile(String.valueOf(aFileGen));
      sourceGen.extractAll(tempDirExcelGenerated.toString());
    }


    System.out.println("<------------- FICHIERS GENERES ------------------>");


    // Extraction des données Excel du Fichier Generated
    for (File fileListExcelGen : tempDirExcelGenerated.toFile().listFiles()) {
      if (fileListExcelGen.getAbsolutePath().endsWith(".xlsx")) {
        System.out.println("NOM DU FICHIER GENERE: " + fileListExcelGen);
        FileInputStream fileInput = new FileInputStream(
            new File(String.valueOf(fileListExcelGen)));
        XSSFWorkbook workbookGen = new XSSFWorkbook(fileInput);
        excelListGen.add(workbookGen);
      }
    }

    // Extraction du Zip parent Fichier Referenced
    ZipFile sourceRef2 = new ZipFile(localproperties.getProperty(ZIP_INPUT_FOLDER) + "/r25/" + refFile);
    sourceRef2.extractAll(tempDirZipReferenced.toString());

    // Extraction des Zips enfants Fichier Referenced
    for (File aFileRef : tempDirZipReferenced.toFile().listFiles()) {
      ZipFile sourceRef = new ZipFile(String.valueOf(aFileRef));
      sourceRef.extractAll(tempDirExcelReferenced.toString());
    }

    System.out.println("<------------- FICHIERS DE REFERENCE ------------------>");

    // Extraction des données Excel du Fichier Referenced
    for (File fileListExcelRef : tempDirExcelReferenced.toFile().listFiles()) {
      if (fileListExcelRef.getAbsolutePath().endsWith(".xlsx")) {
        System.out.println("NOM DU FICHIER DE REFERENCE: " + fileListExcelRef);
        FileInputStream fileInput = new FileInputStream(
            new File(String.valueOf(fileListExcelRef)));
        XSSFWorkbook workbookRef = new XSSFWorkbook(fileInput);
        excelListRef.add(workbookRef);
      }
    }

    softAssert.assertThat(excelListGen.size()).isEqualTo(excelListRef.size());
    for (int a = 0; a < excelListGen.size() && a < excelListRef.size(); a++) {
      if (excelListGen.get(a).getNumberOfSheets() == excelListRef.get(a).getNumberOfSheets()) {
        for (int b = 0; b < excelListGen.get(a).getNumberOfSheets(); b++) {
          System.out.println(excelListRef.get(a));
          System.out.println(excelListGen.get(a));
          System.out.println("WORKBOOKREF = " + excelListRef.get(a).getCTWorkbook());
          System.out.println("WORKBOOKGEN = " + excelListGen.get(a).getCTWorkbook());
          XSSFSheet sheetRef = excelListRef.get(a).getSheetAt(b);
          XSSFSheet sheetGen = excelListGen.get(a).getSheetAt(b);
          for (int i = 2; i < sheetRef.getLastRowNum(); i++) {
            XSSFRow rowRef = sheetRef.getRow(i);
            XSSFRow rowGen = sheetGen.getRow(i);
            for (int j = 0; j < rowRef.getLastCellNum(); j++) {
              XSSFCell cellRef = rowRef.getCell(j);
              XSSFCell cellGen = rowGen.getCell(j);
              System.out.println(cellRef.getReference());
              System.out.println(cellGen.getReference());
              softAssert.assertThat(df.formatCellValue(cellGen)).isEqualTo(df.formatCellValue(cellRef));
            }
          }
        }
      }
    }
    softAssert.assertAll();
  }
}