package io.gmss.fiscad.service;

import io.gmss.fiscad.entities.decoupage.Arrondissement;
import io.gmss.fiscad.entities.decoupage.Commune;
import io.gmss.fiscad.entities.infocad.metier.EnqueteFiltreResponse;
import io.gmss.fiscad.entities.infocad.parametre.Bloc;
import io.gmss.fiscad.entities.infocad.parametre.Structure;
import io.gmss.fiscad.enums.FormatRapport;
import io.gmss.fiscad.enums.RoleActeur;
import io.gmss.fiscad.interfaces.infocad.metier.EnqueteService;
import io.gmss.fiscad.paylaods.request.FiltreEnquetePayLoad;
import io.gmss.fiscad.paylaods.response.report.BlocsParStructureResponse;
import io.gmss.fiscad.paylaods.response.report.EnqueteParBlocResponse;
import io.gmss.fiscad.repositories.decoupage.ArrondissementRepository;
import io.gmss.fiscad.repositories.decoupage.CommuneRepository;
import io.gmss.fiscad.repositories.infocad.metier.EnqueteRepository;
import io.gmss.fiscad.repositories.infocad.parametre.BlocRepository;
import io.gmss.fiscad.repositories.infocad.parametre.StructureRepository;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimplePdfExporterConfiguration;
import net.sf.jasperreports.export.SimplePdfReportConfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import java.io.*;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class ReportService {
    private final BlocRepository blocRepository;
    private final CommuneRepository communeRepository;
    private final ArrondissementRepository arrondissementRepository;
    private final EnqueteRepository enqueteRepository;
    private final StructureRepository structureRepository;
    private final EnqueteService enqueteService;
    @Value("${file.jasper-reports}")
    private String jaspersDir;

    private final ResourceLoader resourceLoader;

    public ReportService(BlocRepository blocRepository, CommuneRepository communeRepository, ArrondissementRepository arrondissementRepository, EnqueteRepository enqueteRepository, StructureRepository structureRepository, EnqueteService enqueteService, ResourceLoader resourceLoader) {
        this.blocRepository = blocRepository;
        this.communeRepository = communeRepository;
        this.arrondissementRepository = arrondissementRepository;
        this.enqueteRepository = enqueteRepository;
        this.structureRepository = structureRepository;
        this.enqueteService = enqueteService;
        this.resourceLoader = resourceLoader;
    }


    public void printPDF(HttpServletResponse response, Map<String, Object> parameters, String jaspers, String fileName, List<?> data) throws JRException, IOException {
        try {

            parameters.put("logoGauche", getJaspersDir() + "/andf.png");
            // parameters.put("logoArcep",imageDir+"/logo-arcep.png" );

            InputStream stream = getStream(getJaspersDir() + jaspers);

            JRDataSource dataSource = new JRBeanCollectionDataSource(data, false);
            JasperPrint jasperPrint = JasperFillManager.fillReport(stream, parameters, dataSource);
            JRPdfExporter exporter = new JRPdfExporter();
            exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
            SimplePdfReportConfiguration reportConfig = new SimplePdfReportConfiguration();
            reportConfig.setSizePageToContent(true);
            reportConfig.setForceLineBreakPolicy(false);
            SimplePdfExporterConfiguration exportConfig = new SimplePdfExporterConfiguration();
            exportConfig.setMetadataAuthor("ANDF");
            exportConfig.setEncrypted(true);
            exportConfig.setAllowedPermissionsHint("PRINTING");
            exporter.setConfiguration(reportConfig);
            exporter.setConfiguration(exportConfig);
            response.setContentType("application/x-download");
            response.setHeader("Content-Disposition", String.format("attachment; filename=\"" + fileName + ".pdf\""));
            OutputStream out = response.getOutputStream();
            JasperExportManager.exportReportToPdfStream(jasperPrint, out);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void printXLSX(HttpServletResponse response, Map<String, Object> parameters, String jaspers, String fileName, List<?> data) throws SQLException, JRException, IOException {
        ServletOutputStream servletOutputStream = response.getOutputStream();
        //parameters.put("logoMEF", imageDir+"/logo_mef-transparent.png");
        // parameters.put("logoArcep",imageDir+"/logo-arcep.png" );
        parameters.put("logoGauche", getJaspersDir() + "/andf.png");
        // parameters.put("logoArcep",imageDir+"/logo-arcep.png" );

        InputStream stream = getStream(getJaspersDir() + jaspers);

        JRDataSource dataSource = new JRBeanCollectionDataSource(data, false);
        JasperPrint jasperPrint = JasperFillManager.fillReport(stream, parameters, dataSource);
        //JRPdfExporter exporter = new JRPdfExporter();
        //exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        SimplePdfReportConfiguration reportConfig = new SimplePdfReportConfiguration();
        reportConfig.setSizePageToContent(true);
        reportConfig.setForceLineBreakPolicy(false);
        SimplePdfExporterConfiguration exportConfig = new SimplePdfExporterConfiguration();
        exportConfig.setMetadataAuthor("ARCEP");
        exportConfig.setEncrypted(true);
        exportConfig.setAllowedPermissionsHint("PRINTING");
        //exporter.setConfiguration(reportConfig);
        //exporter.setConfiguration(exportConfig);
        response.setContentType("application/x-download");
        response.setHeader("Content-Disposition", String.format("attachment; filename=\"" + fileName + ".xlsx\""));
        JRXlsxExporter docxExporter = new JRXlsxExporter();
        docxExporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        docxExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, servletOutputStream);
        docxExporter.exportReport();
    }


    public InputStream getStream(String fileName) throws IOException {
        File initialFile = new File(fileName);
        InputStream stream = new FileInputStream(initialFile);
        return stream;
    }

    private String getResourcePath(String fileName) throws IOException {
        return resourceLoader.getResource("classpath:" + fileName).getFile().getAbsolutePath();
    }

    public String getJaspersDir() {
        return jaspersDir;
    }

    public void imprimerBlocsStructure(HttpServletResponse response, FormatRapport formatRapport, Long structureId) {
        try {
            Optional<Structure> optionalStructure = structureRepository.findById(structureId);
            if (!optionalStructure.isEmpty()) {
                List<BlocsParStructureResponse> blocs = blocRepository.getBlocsParStructureResponse(structureId);

                Map<String, Object> parameters = new HashMap();
                parameters.put("structure", optionalStructure.get().getNom());
                try {
                    String jaspers = "/listBlocParStructure.jasper";
                    if (formatRapport.equals(FormatRapport.PDF)) {
                        printPDF(response, parameters, jaspers, "blocs.pdf", blocs);
                    }
                    if (formatRapport.equals(FormatRapport.XLS)) {
                        printXLSX(response, parameters, jaspers, "blocs.xlsx", blocs);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JRException e) {
                    e.printStackTrace();
                }

            } else {
                System.out.printf("Structure inexistante");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void imprimerEnqueteParBloc(HttpServletResponse response, FormatRapport formatRapport, Long blocId) {
        try {
            Optional<Bloc> optionalBloc = blocRepository.findById(blocId);
            if (!optionalBloc.isEmpty()) {
                Optional<Structure> optionalStructure = structureRepository.findById(optionalBloc.get().getStructure().getId());
                Optional<Arrondissement> optionalArrondissement = arrondissementRepository.findById(optionalBloc.get().getArrondissement().getId());
                Optional<Commune> optionalCommune = communeRepository.findById(optionalArrondissement.get().getCommune().getId());
                List<EnqueteParBlocResponse> enqueteParBlocResponses = enqueteRepository.getEnqueteByBloc(blocId, RoleActeur.PROPRIETAIRE.toString());
                Map<String, Object> parameters = new HashMap();
                parameters.put("structure", optionalStructure.get().getNom());
                parameters.put("bloc", optionalBloc.get().getNom());
                parameters.put("commune", optionalCommune.get().getNom());
                parameters.put("arrondissement", optionalArrondissement.get().getNom());
                try {
                    String jaspers = "/listEnqueteParBloc.jasper";
                    if (formatRapport.equals(FormatRapport.PDF)) {
                        printPDF(response, parameters, jaspers, "listEnqueteParBloc.pdf", enqueteParBlocResponses);
                    }
                    if (formatRapport.equals(FormatRapport.XLS)) {
                        printXLSX(response, parameters, jaspers, "listEnqueteParBloc.xlsx", enqueteParBlocResponses);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JRException e) {
                    e.printStackTrace();
                }

            } else {
                System.out.printf("Structure inexistante");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void imprimerEnqueteParFiltre(HttpServletResponse response, FiltreEnquetePayLoad filtreEnquetePayLoad, FormatRapport formatRapport) {
        try {

            List<EnqueteFiltreResponse> enqueteFiltreResponses = enqueteService.getEnqueteCommuneArrondBlocFiltre(filtreEnquetePayLoad);
            Map<String, Object> parameters = new HashMap();
            try {
                String jaspers = "/listEnqueteParFiltre.jasper";
                if (formatRapport.equals(FormatRapport.PDF)) {
                    printPDF(response, parameters, jaspers, "listEnqueteParFiltre.pdf", enqueteFiltreResponses);
                }
                if (formatRapport.equals(FormatRapport.XLS)) {
                    printXLSX(response, parameters, jaspers, "listEnqueteParFiltre.xlsx", enqueteFiltreResponses);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JRException e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
