<?php

namespace App\Controller\Frontend;

use App\Controller\AbstractController;
use App\Form\SearchListForm;
use App\Repository\Site\BlockStore;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use Dompdf\Dompdf;
use Dompdf\Options;
use Knp\Component\Pager\PaginatorInterface;
use Lc\PietroBundle\Model\AbstractData;
use Lc\PietroBundle\Repository\Dream\DreamStore;
use Lc\PietroBundle\Repository\ProjectBoost\ProjectBoostStore;
use Lc\PietroBundle\Repository\ProjectInspiring\ProjectInspiringStore;
use Lc\PietroBundle\Repository\Revolt\RevoltStore;
use Lc\PietroBundle\Repository\Territory\TerritoryStore;
use Lc\PietroBundle\Repository\Thematic\ThematicStore;
use Lc\SovBundle\Generator\CsvGenerator;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Twig\Environment;
use ReflectionClass;

class CartoController extends AbstractController
{
    protected EntityManagerInterface $em;
    protected DreamStore $dreamStore;
    protected RevoltStore $revoltStore;
    protected ProjectBoostStore $projectBoostStore;
    protected ProjectInspiringStore $projectInspiringStore;
    protected TerritoryStore $territoryStore;
    protected ThematicStore $thematicStore;
    protected BlockStore $blockStore;
    protected PaginatorInterface $paginator;
    protected Environment $templating;
    protected ParameterBagInterface $parameterBag;

    public function __construct(
        EntityManagerInterface $em,
        DreamStore $dreamStore,
        RevoltStore $revoltStore,
        ProjectBoostStore $projectBoostStore,
        ProjectInspiringStore $projectInspiringStore,
        TerritoryStore $territoryStore,
        ThematicStore $thematicStore,
        BlockStore $blockStore,
        PaginatorInterface $paginator,
        Environment $templating,
        ParameterBagInterface $parameterBag
    ) {
        $this->em = $em;
        $this->dreamStore = $dreamStore;
        $this->revoltStore = $revoltStore;
        $this->projectBoostStore = $projectBoostStore;
        $this->projectInspiringStore = $projectInspiringStore;
        $this->territoryStore = $territoryStore;
        $this->thematicStore = $thematicStore;
        $this->blockStore = $blockStore;
        $this->paginator = $paginator;
        $this->templating = $templating;
        $this->parameterBag = $parameterBag;
    }

    public function cartoInteractive()
    {
        $blockCartoInt = $this->blockStore->getOneOnlineByDevAlias('carto-int');

        return $this->render(
            'frontend/carto-int.html.twig',
            [
                'blockCartoInt' => $blockCartoInt,
                'nbContrib' => $this->countContrib()
            ]
        );
    }

    public function cartoListe(Request $request)
    {
        $blockCartoInt = $this->blockStore->getOneOnlineByDevAlias('carto-int');

        $resultArrayPagination = array();
        $form = $this->createForm(SearchListForm::class, null, [
            'method' => 'GET',
        ]);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();

            $resultArray = $this->generateResultArray($data);
            if ($form->get('export_excel')->isClicked()) {
                return $this->exportCsv($resultArray);
            } elseif ($form->get('export_pdf')->isClicked()) {
                return $this->exportPdf($resultArray);
            } else {
                $page = $data['page'];

                $resultArrayPagination = $this->paginator->paginate(
                    $resultArray,
                    $page,
                    10
                );
            }
        } else {
            $resultArray = $this->generateResultArray();
            $resultArrayPagination = $this->paginator->paginate(
                $resultArray,
                1,
                10
            );
        }

        return $this->render(
            'frontend/carto-liste.html.twig',
            [
                'form' => $form->createView(),
                'nbContrib' => $this->countContrib(),
                'resultArray' => $resultArrayPagination,
                'blockCartoInt' => $blockCartoInt,
            ]
        );
    }

    public function cartoCarte()
    {
        $blockCartoInt = $this->blockStore->getOneOnlineByDevAlias('carto-int');

        $resultArray = $this->generateAllResultArray();
        $resultSortArray = array();
        $territoryArray = $this->territoryStore->get();

        foreach ($territoryArray as $territory) {
            $resultSortArray[$territory->getDevAlias()] =
                [
                    AbstractData::TERRITORY => $territory->getId(),
                    AbstractData::CATEGORY_REVOLT => "0",
                    AbstractData::CATEGORY_DREAM => "0",
                    AbstractData::CATEGORY_PROJECTBOOST => "0",
                    AbstractData::CATEGORY_PROJECTINSPIRING => "0",
                ];
        }

        foreach ($resultArray as $result) {
            $className = (new ReflectionClass($result))->getShortName();
            if ($result->getIndividualData()) {
                $devAliasTerritory = $result->getIndividualData()->getTerritory()->getDevAlias();
            } elseif ($result->getCollectifData()->getTerritory()) {
                $devAliasTerritory = $result->getCollectifData()->getTerritory()->getDevAlias();
            }

            $resultSortArray[$devAliasTerritory][$className] = $resultSortArray[$devAliasTerritory][$className] + 1;
        }

        return $this->render(
            'frontend/carto-carte.html.twig',
            [
                'resultSortArray' => $resultSortArray,
                'nbContrib' => $this->countContrib(),
                'blockCartoInt' => $blockCartoInt,
            ]
        );
    }

    public function cartoJson(Request $request)
    {
        $thematicArray = $this->thematicStore->get();
        $data = array();
        $key = 0;

        foreach ($thematicArray as $thematic) {
            $revoltArray = $this->revoltStore->getByThematic($thematic);
            $dreamArray = $this->dreamStore->getByThematic($thematic);
            $projectBoostArray = $this->projectBoostStore->getByThematic($thematic);
            $projectInspArray = $this->projectInspiringStore->getByThematic($thematic);

            $contribArray = array_merge($revoltArray, $dreamArray, $projectBoostArray, $projectInspArray);

            foreach ($contribArray as $contrib) {
                $keyAlreadyHere = array_search($contrib->__toString(), array_column($data, 'name'));
//                si "Nos révoltes" ou "Nos Reves" etc, n'existe pas encore on le créer
                if ($keyAlreadyHere === false) {
                    $data[$key] = [
                        'name' => $contrib->__toString(),
                        'children' => []
                    ];
//                  on insere le premier thème de la contribution
                    $data[$key]['children'][] = [
                        'name' => $thematic->getName(),
                        'id_thematic' => $thematic->getId(),
                        'id_category' => AbstractData::getCategoryByLabel($contrib->__toString()),
                        'nb' => 1,
                    ];
                    $key++;
                } else {
                    $keyTheme = array_search(
                        $thematic->getName(),
                        array_column($data[$keyAlreadyHere]['children'], 'name')
                    );
//                    si le thème de la contribution n'existe pas encore on le créer
                    if ($keyTheme === false) {
                        $data[$keyAlreadyHere]['children'][] = [
                            'name' => $thematic->getName(),
                            'id_thematic' => $thematic->getId(),
                            'id_category' => AbstractData::getCategoryByLabel($contrib->__toString()),
                            'nb' => 1,
                        ];
                    } else {
                        $data[$keyAlreadyHere]['children'][$keyTheme]['nb']++;
                    }
                }
            }
        }

        return new JsonResponse($data);
    }

    private function generateResultArray(
        $data = array(
            'search' => '',
            'category' => array()
        )
    ): array {
        $dreamArray = $revoltArray = $projectBoostArray = $projectInspiringArray = array();

        $subthematic = $data['search'];
        $categoryArray = $data['category'];
        $territoryArray = isset($data['territory']) ? $data['territory'] : new ArrayCollection();
        $thematicArray = isset($data['thematic']) ? $data['thematic'] : new ArrayCollection();

        if (in_array(AbstractData::CATEGORY_DREAM, $categoryArray) || empty($categoryArray)) {
            $dreamArray = $this->dreamStore->filterSearch($subthematic, $territoryArray, $thematicArray);
        }
        if (in_array(AbstractData::CATEGORY_REVOLT, $categoryArray) || empty($categoryArray)) {
            $revoltArray = $this->revoltStore->filterSearch($subthematic, $territoryArray, $thematicArray);
        }
        if (in_array(AbstractData::CATEGORY_PROJECTBOOST, $categoryArray) || empty($categoryArray)) {
            $projectBoostArray = $this->projectBoostStore->filterSearch(
                $subthematic,
                $territoryArray,
                $thematicArray
            );
        }
        if (in_array(AbstractData::CATEGORY_PROJECTINSPIRING, $categoryArray) || empty($categoryArray)) {
            $projectInspiringArray = $this->projectInspiringStore->filterSearch(
                $subthematic,
                $territoryArray,
                $thematicArray
            );
        }

        return array_merge($dreamArray, $revoltArray, $projectBoostArray, $projectInspiringArray);
    }

    public function exportPdf($resultArray = array())
    {
        // Configure Dompdf according to your needs
        $pdfOptions = new Options();
        $pdfOptions->set('defaultFont', 'Arial');

        // Instantiate Dompdf with our options
        $dompdf = new Dompdf($pdfOptions);

        if (empty($resultArray)) {
            $resultArray = $this->generateAllResultArray();
        }

        // Retrieve the HTML generated in our twig
        $html = $this->templating->render('frontend/pdf.html.twig', [
            'resultArray' => $resultArray,
            'css' => file_get_contents(
                $this->parameterBag->get('app.assets_directory') . 'css/pdf.css'
            )
        ]);

        // Load HTML to Dompdf
        $dompdf->loadHtml($html);

        // (Optional) Setup the paper size and orientation 'portrait' or 'portrait'
        $dompdf->setPaper('A4', 'portrait');


        // Render the HTML as PDF
        $dompdf->render();
        $dompdf->stream('Export-pdf.pdf', [
            "Attachment" => true
        ]);
    }

    public function exportCsv($resultArray = array())
    {
        $csv = new CsvGenerator();
        $csv->enableConvertEncoding('ISO-8859-1');
        $csv->setTitle('Export_Liste', true);

        $columns = [
            'category' => 'Catégorie',
            'thematic' => 'Thématique',
            'subthematic' => 'Contribution',
            'territory' => 'Lieu'
        ];
        $csv->setColumns($columns);

        if (empty($resultArray)) {
            $resultArray = $this->generateAllResultArray();
        }

        $csv = $this->generateCsvData($csv, $resultArray);

        return $csv->getReponse();
    }

    private function generateAllResultArray(): array
    {
        $dreamArray = $this->dreamStore->get();
        $revoltArray = $this->revoltStore->get();
        $projectBoostArray = $this->projectBoostStore->get();
        $projectInspiringArray = $this->projectInspiringStore->get();

        return array_merge($dreamArray, $revoltArray, $projectBoostArray, $projectInspiringArray);
    }

    private function generateCsvData($csv, $resultArray)
    {
        foreach ($resultArray as $result) {
            $territory = $subthematic = $thematic = "";
            if ($result->getIndividualData()) {
                $territory = $result->getIndividualData()->getTerritory()->getName();
            } elseif ($result->getCollectifData()->getTerritory()) {
                $territory = $result->getCollectifData()->getTerritory()->getName();
            }

            if ($result->getSubthematic()) {
                $subthematic = $result->getSubthematic()->getName();
            }

            if ($result->getThematic()) {
                $thematic = $result->getThematic()->getName();
            }

            $data = [
                'category' => $result->__toString(),
                'thematic' => $thematic,
                'subthematic' => $subthematic,
                'territory' => $territory
            ];

            $csv->row($data);
        }

        return $csv;
    }
}