<?php

namespace App\Controller\Admin\Security;

use DateTimeImmutable;
use Exception;
use LogicException;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security as Security;

#[Route('/admin/databases/backup')]
#[Security("is_granted('ROLE_SUPER_ADMIN')")]
class AdminDatabaseBackupController extends AbstractController
{
    #[Route('/', name:"admin.databases.index", methods: ['GET'])]
    /**
     * @param KernelInterface $kernel
     * @param string $projectDirectory
     * @return Response
     * @throws Exception
     */
    public function index(
        KernelInterface $kernel,
        string $projectDirectory
    ): Response {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
        $user = $this->getUser();
        if ($user === null) {
            throw new LogicException('User can not be null');
        }

        $application = new Application($kernel);
        $application->setAutoExit(false);

        $input = new ArrayInput([
            'command' => 'app:database-backup'
        ]);

        $output = new NullOutput();

        try {
            $application->run($input, $output);
        } catch (Exception $error) {
            throw new Exception($error);
        }

        $backupFile = "$projectDirectory/var/backup/backup.sql";
        $currentDatetimeString = (new DateTimeImmutable('now'))->format('d-m-Y-H-i-s');
        $backupFileRenamed = "$projectDirectory/var/backup/backup-$currentDatetimeString.sql";

        $fileSystem = new Filesystem();
        try {
            $fileSystem->rename($backupFile, $backupFileRenamed);
        } catch (IOException $error) {
            throw new IOException($error);
        }

        if (file_exists($backupFileRenamed) === true) {
            header('Content-Description: File transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename="' . basename($backupFileRenamed) . '"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-length: ' . filesize($backupFileRenamed));

            while (ob_get_level()) {
                ob_get_clean();
            }

            readfile($backupFileRenamed);

            exit();
        }

        return new Response();
    }
}
