<?php

/*
 * @author TRYDEA - 2024
 */

namespace Webapp\FileManagement\Controller;

use Shared\Authentication\Entity\Site;
use Shared\TransferSync\Entity\StatusDataEntry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Vich\UploaderBundle\Handler\DownloadHandler;
use Webapp\Core\Entity\Experiment;
use Webapp\Core\Entity\Platform;
use Webapp\FileManagement\Entity\ResponseFile;
use Webapp\FileManagement\Service\MobileWriterService;
use Webapp\FileManagement\Service\WebappWriterService;
use Webapp\FileManagement\Service\WebappXmlWriterService;
use Webapp\FileManagement\Voters\UserLinkedFileJobVoter;

/**
 * Class DownloadFileController.
 */
class DownloadFileController extends AbstractController
{
    /**
     * @Route("/api/download/response-files/{file}", name="downloadReturnFile")
     */
    public function executeDownload(ResponseFile $file, DownloadHandler $downloadHandler): Response
    {
        $this->denyAccessUnlessGranted(UserLinkedFileJobVoter::DOWNLOAD, $file);
        $response = $downloadHandler->downloadObject($file, 'file');
        $response->headers->set('Content-Type', 'application/zip');

        return $response;
    }

    /**
     * @Route("/api/download/project/{project}", name="downloadProjectFile")
     */
    public function exportProjectFile(StatusDataEntry $project, MobileWriterService $writerService): Response
    {
        $response = new StreamedResponse(function () use ($writerService, $project) {
            $outputStream = fopen('php://output', 'w');
            $zipStream = tmpfile();
            $writerService->constructProjectZipFile($project->getRequest(), stream_get_meta_data($zipStream)['uri']);
            stream_copy_to_stream(fopen(stream_get_meta_data($zipStream)['uri'], 'r'), $outputStream);
            fclose($zipStream);
        });
        $response->headers->set('Content-Type', 'application/zip');
        $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $project->getRequest()->getName().'.zip',
            iconv('UTF-8', 'ASCII//TRANSLIT', $project->getRequest()->getName().'.zip')
        ));

        return $response;
    }

    /**
     * @Route("/api/download/experiment/{experiment}", name="downloadExperimentFile")
     */
    public function exportExperimentFile(Experiment $experiment, WebappXmlWriterService $writerService): Response
    {
        $response = new Response($writerService->generateExperiment($experiment));
        $this->setXmlReponseHeaders($response, $experiment->getName());

        return $response;
    }

    /**
     * @Route("/api/download/platform/{platform}", name="downloadPlatformFile")
     */
    public function exportPlatformFile(Platform $platform, WebappXmlWriterService $writerService): Response
    {
        $response = new Response($writerService->generatePlatform($platform));
        $this->setXmlReponseHeaders($response, $platform->getName());

        return $response;
    }

    /**
     * @Route("/api/download/platformWithData/{platform}", name="downloadPlatformWithDataFile")
     */
    public function exportPlatformWithDataFile(Platform $platform, WebappXmlWriterService $writerService): Response
    {
        $response = new Response($writerService->generatePlatformWithData($platform));
        $this->setXmlReponseHeaders($response, $platform->getName());

        return $response;
    }

    /**
     * @Route("/api/download/variables/{site}", name="downloadVariablesFile")
     */
    public function exportVariablesFile(Site $site, Request $request, WebappWriterService $writerService): Response
    {
        $datas = $request->query->get('datas') ?? [];

        $variablesFile = $writerService->createVariableCollectionFile($site, $datas);
        $filename = $site->getLabel().'-variables.'.$variablesFile->getExtension();

        $response = new BinaryFileResponse($variablesFile, 200, [], true, HeaderUtils::DISPOSITION_ATTACHMENT);
        $response->setContentDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $filename,
            iconv('UTF-8', 'ASCII//TRANSLIT', $filename)
        );
        $response->deleteFileAfterSend();

        return $response;
    }

    private function setXmlReponseHeaders(Response $response, string $filename): void
    {
        $response->headers->set('Content-Type', 'application/xml');
        $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $filename.'.xml',
            iconv('UTF-8', 'ASCII//TRANSLIT', $filename.'.xml')
        ));
    }
}
