<?php

/**
 * Copyright Maarch since 2008 under licence GPLv3.
 * See LICENCE.txt file at the root folder for more details.
 * This file is part of Maarch software.
 */

/**
 * @brief Installer Controller
 *
 * @author dev@maarch.org
 */

namespace SrcCore\controllers;

use ContentManagement\controllers\DocumentEditorController;
use Respect\Validation\Validator;
use Slim\Http\Request;
use Slim\Http\Response;
use SrcCore\models\AuthenticationModel;
use SrcCore\models\CoreConfigModel;
use SrcCore\models\DatabaseModel;
use SrcCore\models\DatabasePDO;
use User\models\UserModel;

class InstallerController
{
    public function getPrerequisites(Request $request, Response $response)
    {
        $phpVersion = phpversion();
        $phpVersionValid = (version_compare(PHP_VERSION, '7.2') >= 0);

        exec('whereis unoconv', $output, $return);
        $output = explode(':', $output[0]);
        $unoconv = !empty($output[1]);

        exec('whereis wkhtmltopdf', $outputWk, $returnWk);
        $outputWk = explode(':', $outputWk[0]);
        $wkhtmlToPdf = !empty($outputWk[1]);

        exec('whereis netcat', $outputNetcat, $returnNetcat);
        $outputNetcat = explode(':', $outputNetcat[0]);

        exec('whereis nmap', $outputNmap, $returnNmap);
        $outputNmap = explode(':', $outputNmap[0]);
        $netcatOrNmap = !empty($outputNetcat[1]) || !empty($outputNmap[1]);

        $pdoPgsql = @extension_loaded('pdo_pgsql');
        $pgsql = @extension_loaded('pgsql');
        $mbstring = @extension_loaded('mbstring');
        $fileinfo = @extension_loaded('fileinfo');
        $gd = @extension_loaded('gd');
        $imagick = @extension_loaded('imagick');
        $gettext = @extension_loaded('gettext');
        $curl = @extension_loaded('curl');
        $zip = @extension_loaded('zip');
        $json = @extension_loaded('json');
        $xml = @extension_loaded('xml');

        $writable = is_writable('.') && is_readable('.');

        $displayErrors = (ini_get('display_errors') == '1');
        $errorReporting = CoreController::getErrorReportingFromPhpIni();
        $errorReporting = !in_array(8, $errorReporting);

        $prerequisites = [
            'phpVersion'        => $phpVersion,
            'phpVersionValid'   => $phpVersionValid,
            'unoconv'           => $unoconv,
            'wkhtmlToPdf'           => $wkhtmlToPdf,
            'netcatOrNmap'      => $netcatOrNmap,
            'pdoPgsql'          => $pdoPgsql,
            'pgsql'             => $pgsql,
            'mbstring'          => $mbstring,
            'fileinfo'          => $fileinfo,
            'gd'                => $gd,
            'imagick'           => $imagick,
            'json'              => $json,
            'gettext'           => $gettext,
            'xml'               => $xml,
            'curl'              => $curl,
            'zip'               => $zip,
            'writable'          => $writable,
            'displayErrors'     => $displayErrors,
            'errorReporting'    => $errorReporting
        ];

        return $response->withJson(['prerequisites' => $prerequisites]);
    }

    public function checkDatabaseConnection(Request $request, Response $response)
    {
        $queryParams = $request->getQueryParams();

        if (!Validator::stringType()->notEmpty()->validate($queryParams['server'])) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams server is empty or not a string']);
        } elseif (!Validator::intVal()->notEmpty()->validate($queryParams['port'])) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams port is empty or not an integer']);
        } elseif (!Validator::stringType()->notEmpty()->validate($queryParams['user'])) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams user is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($queryParams['password'])) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams password is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($queryParams['name'])) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams name is empty or not a string']);
        } elseif (!Validator::length(1, 50)->validate($queryParams['name'])) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams name length is not valid']);
        } elseif (strpbrk($queryParams['name'], '"; \\') !== false) {
            return $response->withStatus(400)->withJson(['errors' => 'QueryParams name is not valid']);
        }

        $options = [
            \PDO::ATTR_ERRMODE      => \PDO::ERRMODE_EXCEPTION,
            \PDO::ATTR_CASE         => \PDO::CASE_NATURAL
        ];

        $firstTry = true;
        $dsn = "pgsql:host={$queryParams['server']};port={$queryParams['port']};dbname={$queryParams['name']}";
        try {
            $db = new \PDO($dsn, $queryParams['user'], $queryParams['password'], $options);
        } catch (\PDOException $PDOException) {
            $firstTry = false;
            $dsn = "pgsql:host={$queryParams['server']};port={$queryParams['port']};dbname=postgres";
            try {
                $db = new \PDO($dsn, $queryParams['user'], $queryParams['password'], $options);
            } catch (\PDOException $PDOException) {
                return $response->withStatus(400)->withJson(['errors' => 'Database connection failed']);
            }
        }

        if ($firstTry) {
            $query = $db->query("SELECT table_name FROM information_schema.tables WHERE table_schema not in ('pg_catalog', 'information_schema')");
            $row = $query->fetch(\PDO::FETCH_ASSOC);
            if (!empty($row)) {
                return $response->withStatus(400)->withJson(['errors' => 'Given database has tables']);
            }
            return $response->withJson(['warning' => 'Database exists']);
        }

        return $response->withStatus(204);
    }

    public function getSQLDataFiles(Request $request, Response $response)
    {
        $dataFiles = [];

        $sqlFiles =  scandir('sql');
        foreach ($sqlFiles as $sqlFile) {
            if ($sqlFile == '.' || $sqlFile == '..') {
                continue;
            }
            if (strpos($sqlFile, 'data_') === 0) {
                $dataFiles[] = str_replace('.sql', '', $sqlFile);
            }
        }

        return $response->withJson(['dataFiles' => $dataFiles]);
    }

    public function checkDocservers(Request $request, Response $response)
    {
        $queryParams = $request->getQueryParams();

        if (!Validator::stringType()->notEmpty()->validate($queryParams['path'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Queryparams path is empty or not a string']);
        } elseif (strpbrk($queryParams['path'], '"\'<>|*:?') !== false) {
            return $response->withStatus(400)->withJson(['errors' => 'Body path is not valid']);
        }

        $path = urldecode($queryParams['path']);
        $path = preg_replace('/\/{2,}/', '/', $path);
        $path = rtrim($path, '/');

        $multiplesPaths = explode('/', $path);

        while (!empty($multiplesPaths)) {
            $pathToTest = implode('/', $multiplesPaths);
            if (empty($pathToTest)) {
                $pathToTest = '/';
            }
            if (is_dir($pathToTest)) {
                if (!is_readable($pathToTest) || !is_writable($pathToTest)) {
                    return $response->withStatus(400)->withJson(['errors' => "Queryparams path is not readable or writable"]);
                }
                break;
            }
            unset($multiplesPaths[count($multiplesPaths) - 1]);
        }

        return $response->withStatus(204);
    }

    public function checkCustomName(Request $request, Response $response)
    {
        $queryParams = $request->getQueryParams();

        if (!Validator::stringType()->notEmpty()->validate($queryParams['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Queryparams customId is empty or not a string']);
        } elseif (!preg_match('/^[a-zA-Z0-9_\-]*$/', $queryParams['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Queryparams customId has unauthorized characters']);
        }

        if (is_dir("custom/{$queryParams['customId']}")) {
            return $response->withStatus(400)->withJson(['errors' => "Custom already exists"]);
        }

        $customFile = CoreConfigModel::getJsonLoaded(['path' => 'custom/custom.json']);
        if (!empty($customFile)) {
            foreach ($customFile as $value) {
                if ($value['id'] == $queryParams['customId']) {
                    return $response->withStatus(400)->withJson(['errors' => "Custom already exists in custom.json"]);
                }
            }
        }

        return $response->withStatus(204);
    }

    public function createCustom(Request $request, Response $response)
    {
        $body = $request->getParsedBody();

        if (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId is empty or not a string']);
        } elseif (!preg_match('/^[a-zA-Z0-9_\-]*$/', $body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId has unauthorized characters']);
        }

        if (is_dir("custom/{$body['customId']}")) {
            return $response->withStatus(400)->withJson(['errors' => 'Custom with this name already exists']);
        } elseif (!@mkdir("custom/{$body['customId']}/apps/maarch_entreprise/xml", 0755, true)) {
            return $response->withStatus(400)->withJson(['errors' => 'Custom folder creation failed']);
        }

        if (!is_file("custom/custom.json")) {
            $fp = fopen('custom/custom.json', 'w');
            fwrite($fp, json_encode([], JSON_PRETTY_PRINT));
            fclose($fp);
        }

        $customFile = CoreConfigModel::getJsonLoaded(['path' => 'custom/custom.json']);
        $customFile[] = [
            'id'    => $body['customId'],
            'uri'   => null,
            'path'  => $body['customId']
        ];
        $fp = fopen('custom/custom.json', 'w');
        fwrite($fp, json_encode($customFile, JSON_PRETTY_PRINT));
        fclose($fp);

        $jsonFile = [
            'config'    => [
                'lang'              => $body['lang'] ?? 'fr',
                'applicationName'   => $body['applicationName'] ?? $body['customId'],
                'cookieTime'        => 10080,
                'timezone'          => 'Europe/Paris',
                'maarchDirectory'   => realpath('.') . '/',
                'customID'          => $body['customId'],
                'maarchUrl'         => ''
            ],
            'database'  => []
        ];
        $fp = fopen("custom/{$body['customId']}/apps/maarch_entreprise/xml/config.json", 'w');
        fwrite($fp, json_encode($jsonFile, JSON_PRETTY_PRINT));
        fclose($fp);

        $cmd = 'ln -s ' . realpath('.') . "/ {$body['customId']}";
        exec($cmd);

        file_put_contents("custom/{$body['customId']}/initializing.lck", 1);

        return $response->withStatus(204);
    }

    public function createDatabase(Request $request, Response $response)
    {
        $body = $request->getParsedBody();

        if (!Validator::stringType()->notEmpty()->validate($body['server'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body server is empty or not a string']);
        } elseif (!Validator::intVal()->notEmpty()->validate($body['port'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body port is empty or not an integer']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['user'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body user is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['password'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body password is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['name'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body name is empty or not a string']);
        } elseif (!Validator::length(1, 50)->validate($body['name'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body name length is not valid']);
        } elseif (strpbrk($body['name'], '"; \\') !== false) {
            return $response->withStatus(400)->withJson(['errors' => 'Body name is not valid']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId is empty or not a string']);
        } elseif (!is_file("custom/{$body['customId']}/initializing.lck")) {
            return $response->withStatus(403)->withJson(['errors' => 'Custom is already installed']);
        } elseif (!is_file("custom/{$body['customId']}/apps/maarch_entreprise/xml/config.json")) {
            return $response->withStatus(400)->withJson(['errors' => 'Custom does not exist']);
        }

        $options = [
            \PDO::ATTR_ERRMODE      => \PDO::ERRMODE_EXCEPTION,
            \PDO::ATTR_CASE         => \PDO::CASE_NATURAL
        ];

        $connection = "host={$body['server']} port={$body['port']} user={$body['user']} password={$body['password']} dbname={$body['name']}";
        $connected = @pg_connect($connection);
        if ($connected) {
            pg_close();
            $dsn = "pgsql:host={$body['server']};port={$body['port']};dbname={$body['name']}";
            $db = new \PDO($dsn, $body['user'], $body['password'], $options);

            $query = $db->query("SELECT table_name FROM information_schema.tables WHERE table_schema not in ('pg_catalog', 'information_schema')");
            $row = $query->fetch(\PDO::FETCH_ASSOC);
            if (!empty($row)) {
                return $response->withStatus(400)->withJson(['errors' => 'Given database has tables']);
            }
        } else {
            $dsn = "pgsql:host={$body['server']};port={$body['port']};dbname=postgres";
            try {
                $db = new \PDO($dsn, $body['user'], $body['password'], $options);
            } catch (\PDOException $PDOException) {
                return $response->withStatus(400)->withJson(['errors' => 'Database connection failed']);
            }

            $db->query("CREATE DATABASE \"{$body['name']}\" WITH TEMPLATE template0 ENCODING = 'UTF8'");
            $db->query("ALTER DATABASE \"{$body['name']}\" SET DateStyle =iso, dmy");

            $dsn = "pgsql:host={$body['server']};port={$body['port']};dbname={$body['name']}";
            $db = new \PDO($dsn, $body['user'], $body['password'], $options);
        }

        if (!is_file('sql/structure.sql')) {
            return $response->withStatus(400)->withJson(['errors' => 'File sql/structure.sql does not exist']);
        }
        $fileContent = file_get_contents('sql/structure.sql');
        $result = $db->exec($fileContent);
        if ($result === false) {
            return $response->withStatus(400)->withJson(['errors' => 'Request failed : run structure.sql']);
        }

        if (!empty($body['data'])) {
            if (!is_file("sql/{$body['data']}.sql")) {
                return $response->withStatus(400)->withJson(['errors' => "File sql/{$body['data']}.sql does not exist"]);
            }
            $fileContent = file_get_contents("sql/{$body['data']}.sql");
            $result = $db->exec($fileContent);
            if ($result ===  false) {
                return $response->withStatus(400)->withJson(['errors' => "Request failed : run {$body['data']}.sql"]);
            }
        }

        $configFile = CoreConfigModel::getJsonLoaded(['path' => "custom/{$body['customId']}/apps/maarch_entreprise/xml/config.json"]);
        $configFile['database'] = [
            [
                "server"    => $body['server'],
                "port"      => $body['port'],
                "type"      => 'POSTGRESQL',
                "name"      => $body['name'],
                "user"      => $body['user'],
                "password"  => $body['password']
            ]
        ];

        $fp = fopen("custom/{$body['customId']}/apps/maarch_entreprise/xml/config.json", 'w');
        fwrite($fp, json_encode($configFile, JSON_PRETTY_PRINT));
        fclose($fp);

        return $response->withStatus(204);
    }

    public function createDocservers(Request $request, Response $response)
    {
        $body = $request->getParsedBody();

        if (!Validator::stringType()->notEmpty()->validate($body['path'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body path is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId is empty or not a string']);
        } elseif (!is_file("custom/{$body['customId']}/initializing.lck")) {
            return $response->withStatus(403)->withJson(['errors' => 'Custom is already installed']);
        } elseif (!is_file("custom/{$body['customId']}/apps/maarch_entreprise/xml/config.json")) {
            return $response->withStatus(400)->withJson(['errors' => 'Custom does not exist']);
        } elseif (strpbrk($body['path'], '"\'<>|*:?') !== false) {
            return $response->withStatus(400)->withJson(['errors' => 'Body path is not valid']);
        }

        $body['path'] = preg_replace('/\/{2,}/', '/', $body['path']);
        $body['path'] = rtrim($body['path'], '/');

        if (!is_dir($body['path'])) {
            if (!@mkdir($body['path'], 0755, true)) {
                return $response->withStatus(400)->withJson(['errors' => "Folder creation failed for path : {$body['path']}"]);
            }
        } elseif (!is_readable($body['path']) || !is_writable($body['path'])) {
            return $response->withStatus(400)->withJson(['errors' => "Body path is not readable or writable"]);
        }

        $docservers = [
            'AI'                        => 'ai',
            'RESOURCES'                 => 'resources',
            'ATTACHMENTS'               => 'attachments',
            'CONVERT_RESOURCES'         => 'convert_resources',
            'CONVERT_ATTACH'            => 'convert_attachments',
            'TNL_RESOURCES'             => 'thumbnails_resources',
            'TNL_ATTACHMENTS'           => 'thumbnails_attachments',
            'FULLTEXT_RESOURCES'        => 'fulltext_resources',
            'FULLTEXT_ATTACHMENTS'      => 'fulltext_attachments',
            'TEMPLATES'                 => 'templates',
            'ARCHIVETRANSFER'           => 'archive_transfer',
            'ACKNOWLEDGEMENT_RECEIPTS'  => 'acknowledgement_receipts'
        ];

        foreach ($docservers as $docserver) {
            if (!@mkdir("{$body['path']}/{$body['customId']}/{$docserver}", 0755, true)) {
                return $response->withStatus(400)->withJson(['errors' => "Docserver folder creation failed for path : {$body['path']}/{$body['customId']}/{$docserver}"]);
            }
        }

        $templatesPath = "{$body['path']}/{$body['customId']}/templates/0000";
        if (!@mkdir($templatesPath, 0755, true)) {
            return $response->withJson(['success' => "Docservers created but templates folder creation failed"]);
        }

        $templatesToCopy =  scandir('install/templates/0000');
        foreach ($templatesToCopy as $templateToCopy) {
            if ($templateToCopy == '.' || $templateToCopy == '..') {
                continue;
            }

            copy("install/templates/0000/{$templateToCopy}", "{$templatesPath}/{$templateToCopy}");
        }

        DatabasePDO::reset();
        new DatabasePDO(['customId' => $body['customId']]);
        DatabaseModel::update([
            'table'     => 'docservers',
            'postSet'   => ['path_template' => "replace(path_template, '/opt/maarch/docservers', '{$body['path']}/{$body['customId']}')"],
            'where'     => ['1 = 1']
        ]);

        return $response->withStatus(204);
    }

    public function createCustomization(Request $request, Response $response)
    {
        $body = $request->getParsedBody();

        if (!Validator::stringType()->notEmpty()->validate($body['bodyLoginBackground'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body bodyLoginBackground is empty']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['logo'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body logo is empty']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId is empty or not a string']);
        } elseif (!preg_match('/^[a-zA-Z0-9_\-]*$/', $body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId has unauthorized characters']);
        } elseif (!is_file("custom/{$body['customId']}/initializing.lck")) {
            return $response->withStatus(403)->withJson(['errors' => 'Custom is already installed']);
        }

        mkdir("custom/{$body['customId']}/img", 0755, true);
        if (strpos($body['bodyLoginBackground'], 'data:image/jpeg;base64,') === false) {
            if (!is_file("dist/{$body['bodyLoginBackground']}")) {
                return $response->withStatus(400)->withJson(['errors' => 'Body bodyLoginBackground does not exist']);
            }
            copy("dist/{$body['bodyLoginBackground']}", "custom/{$body['customId']}/img/bodylogin.jpg");
        } else {
            $tmpPath = CoreConfigModel::getTmpPath();
            $tmpFileName = $tmpPath . 'installer_body_' . rand() . '_file.jpg';
            $body['bodyLoginBackground'] = str_replace('data:image/jpeg;base64,', '', $body['bodyLoginBackground']);
            $file = base64_decode($body['bodyLoginBackground']);
            file_put_contents($tmpFileName, $file);

            $size = strlen($file);
            $imageSizes = getimagesize($tmpFileName);
            if ($imageSizes[0] < 1920 || $imageSizes[1] < 1080) {
                return $response->withStatus(400)->withJson(['errors' => 'BodyLogin image is not wide enough']);
            } elseif ($size > 10000000) {
                return $response->withStatus(400)->withJson(['errors' => 'BodyLogin size is not allowed']);
            }
            copy($tmpFileName, "custom/{$body['customId']}/img/bodylogin.jpg");
        }

        if (strpos($body['logo'], 'data:image/svg+xml;base64,') !== false) {
            $tmpPath = CoreConfigModel::getTmpPath();
            $tmpFileName = $tmpPath . 'installer_logo_' . rand() . '_file.svg';
            $body['logo'] = str_replace('data:image/svg+xml;base64,', '', $body['logo']);
            $file = base64_decode($body['logo']);
            file_put_contents($tmpFileName, $file);

            $size = strlen($file);
            if ($size > 5000000) {
                return $response->withStatus(400)->withJson(['errors' => 'Logo size is not allowed']);
            }
            copy($tmpFileName, "custom/{$body['customId']}/img/logo.svg");
        }

        DatabasePDO::reset();
        new DatabasePDO(['customId' => $body['customId']]);
        DatabaseModel::update([
            'table'     => 'parameters',
            'set'       => ['param_value_string' => $body['loginMessage'] ?? ''],
            'where'     => ['id = ?'],
            'data'      => ['loginpage_message']
        ]);
        DatabaseModel::update([
            'table'     => 'parameters',
            'set'       => ['param_value_string' => $body['homeMessage'] ?? ''],
            'where'     => ['id = ?'],
            'data'      => ['homepage_message']
        ]);

        return $response->withStatus(204);
    }

    public function updateAdministrator(Request $request, Response $response)
    {
        $body = $request->getParsedBody();

        if (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId is empty or not a string']);
        } elseif (!preg_match('/^[a-zA-Z0-9_\-]*$/', $body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId has unauthorized characters']);
        } elseif (!is_file("custom/{$body['customId']}/initializing.lck")) {
            return $response->withStatus(403)->withJson(['errors' => 'Custom is already installed']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['login']) && preg_match("/^[\w.@-]*$/", $body['login'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body login is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['firstname'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body firstname is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['lastname'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body lastname is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['password'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body password is empty or not a string']);
        } elseif (!Validator::stringType()->notEmpty()->validate($body['email']) || !filter_var($body['email'], FILTER_VALIDATE_EMAIL)) {
            return $response->withStatus(400)->withJson(['errors' => 'Body email is empty, not a string or not a valid email']);
        }

        DatabasePDO::reset();
        new DatabasePDO(['customId' => $body['customId']]);

        UserModel::create([
            'user' => [
                'userId'        => $body['login'],
                'firstname'     => $body['firstname'],
                'lastname'      => $body['lastname'],
                'mail'          => $body['email'],
                'preferences'   => json_encode(['documentEdition' => 'java']),
                'password'      => $body['password']
            ]
        ]);

        DatabaseModel::update([
            'table'     => 'users',
            'set'       => [
                'mail'      => $body['email']
            ],
            'where'     => ['mail = ?'],
            'data'      => ['support@maarch.fr']
        ]);

        return $response->withStatus(204);
    }

    public function terminateInstaller(Request $request, Response $response)
    {
        $body = $request->getParsedBody();

        if (!Validator::stringType()->notEmpty()->validate($body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId is empty or not a string']);
        } elseif (!preg_match('/^[a-zA-Z0-9_\-]*$/', $body['customId'])) {
            return $response->withStatus(400)->withJson(['errors' => 'Body customId has unauthorized characters']);
        } elseif (!is_file("custom/{$body['customId']}/initializing.lck")) {
            return $response->withStatus(403)->withJson(['errors' => 'Custom is already installed']);
        }

        unlink("custom/{$body['customId']}/initializing.lck");

        $url = UrlController::getCoreUrl();

        $explodedUrl = explode('/', rtrim($url, '/'));
        $lastPart = $explodedUrl[count($explodedUrl) - 1];
        if (is_file('custom/custom.json')) {
            $jsonFile = file_get_contents('custom/custom.json');
            if (!empty($jsonFile)) {
                $jsonFile = json_decode($jsonFile, true);
                foreach ($jsonFile as $value) {
                    if (!empty($value['path']) && $value['path'] == $lastPart) {
                        $url = str_replace("/{$lastPart}", '', $url);
                    }
                }
            }
        }

        $url .= $body['customId'] . '/dist/index.html';

        return $response->withJson(['url' => $url]);
    }
}