<?php

namespace QUI\System\Console\Tools;

use QUI;

use function date;
use function dirname;
use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function is_dir;
use function ltrim;
use function mkdir;
use function parse_ini_file;
use function rename;
use function str_replace;
use function trim;

/**
 * Generate the system htaccess file
 */
class Htaccess extends QUI\System\Console\Tool
{
    private const CUSTOM_HTACCESS_FILE_PATH = ETC_DIR . 'webserver/apache/htaccess.custom.php';

    public function __construct()
    {
        $this->systemTool = true;

        $this->setName('quiqqer:htaccess')
            ->setDescription('Generate the htaccess File.');
    }

    /**
     * (non-PHPdoc)
     *
     * @see \QUI\System\Console\Tool::execute()
     */
    public function execute(): void
    {
        $this->writeLn('Generating HTACCESS ...');

        $htaccessBackupFile = VAR_DIR . 'backup/htaccess_' . date('Y-m-d__H_i_s');
        $htaccessFile = CMS_DIR . '.htaccess';

        $config = parse_ini_file(ETC_DIR . "conf.ini.php", true);

        if (!isset($config['webserver']['type'])) {
            $this->writeLn('Webservertype is not configured!', "red");

            return;
        }

        // create backup
        if (file_exists($htaccessFile)) {
            file_put_contents(
                $htaccessBackupFile,
                file_get_contents($htaccessFile)
            );

            $this->writeLn('You can find a .htaccess Backup File at:');
            $this->writeLn($htaccessBackupFile);
        } else {
            $this->writeLn(
                'No .htaccess File found. Could not create a backup.',
                'red'
            );
        }

        $this->resetColor();


        file_put_contents($htaccessFile, $this->generateHtaccessContent());

        $this->writeLn();
        $this->resetColor();
    }

    protected function generateBody(): string
    {
        $URL_DIR = URL_DIR;
        $URL_SYS_DIR = URL_SYS_DIR;

        if ($URL_DIR != '/') {
            $URL_SYS_DIR = str_replace($URL_DIR, '', URL_SYS_DIR);
        }

        $URL_SYS_DIR = ltrim($URL_SYS_DIR, '/');

        $Engine = QUI::getTemplateManager()->getEngine();
        $Engine->assign([
            'forceHttps' => (bool)QUI::conf("webserver", "forceHttps"),
            'quiqqerBin' => URL_OPT_DIR . 'quiqqer/core/bin',
            'quiqqerLib' => URL_OPT_DIR . 'quiqqer/core/src',
            'quiqqerSys' => URL_OPT_DIR . 'quiqqer/core/admin',
            'URL_DIR' => $URL_DIR,
            'URL_SYS_ADMIN_DIR' => trim($URL_SYS_DIR, '/'),
            'URL_SYS_DIR' => $URL_SYS_DIR,
        ]);

        return $Engine->fetch(OPT_DIR . 'quiqqer/core/src/templates/htaccess.tpl');
    }

    /**
     * Checks if the htaccess file would change if it gets generated again
     */
    public function hasModifications(): bool
    {
        $htaccessFile = CMS_DIR . '.htaccess';

        return trim(file_get_contents($htaccessFile)) !== trim($this->generateHtaccessContent());
    }

    private function generateHtaccessContent(): string
    {
        $htaccessContent = <<<HTACCESS
{$this->generateHeader()}

# >>> custom htaccess content >>>
{$this->getCustomHtaccessContent()}
# <<< custom htaccess content <<<


HTACCESS;

        try {
            QUI::getEvents()->fireEvent('onHtaccessGenerate', [&$htaccessContent]);
        } catch (\Exception $exception) {
            QUI\System\Log::addError($exception->getMessage());
        }

        return $htaccessContent . $this->generateBody();
    }

    private function generateHeader(): string
    {
        $customHtaccessFilePath = self::CUSTOM_HTACCESS_FILE_PATH;

        return <<<HEADER
#  _______          _________ _______  _______  _______  _______
# (  ___  )|\     /|\__   __/(  ___  )(  ___  )(  ____ \(  ____ )
# | (   ) || )   ( |   ) (   | (   ) || (   ) || (    \/| (    )|
# | |   | || |   | |   | |   | |   | || |   | || (__    | (____)|
# | |   | || |   | |   | |   | |   | || |   | ||  __)   |     __)
# | | /\| || |   | |   | |   | | /\| || | /\| || (      | (\ (
# | (_\ \ || (___) |___) (___| (_\ \ || (_\ \ || (____/\| ) \ \__
# (____\/_)(_______)\_______/(____\/_)(____\/_)(_______/|/   \__/
#
# This htaccess file was automatically generated by QUIQQER.
# Do not edit this file manually - your changes will be overwritten.
#
# You can extend it by doing the following:
# 1. Edit "$customHtaccessFilePath"
# 2. Regenerate this file via "./console quiqqer:htaccess" 
#
# Further information: https://dev.quiqqer.com/quiqqer/core/wikis/htaccess
HEADER;
    }

    private function getCustomHtaccessContent(): string
    {
        $this->migrateCustomHtaccessFile();

        if (!file_exists(self::CUSTOM_HTACCESS_FILE_PATH)) {
            $this->createCustomHtaccessFile(<<<HTACCESS
#<?php exit; ?>
# This file will be included into the auto generated .htaccess file
# You can extend the .htaccess file by editing this file

HTACCESS
            );
        }

        return file_get_contents(self::CUSTOM_HTACCESS_FILE_PATH);
    }

    /**
     * @todo remove migration on next major release (3.x)
     *
     * @return void
     */
    private function migrateCustomHtaccessFile(): void
    {
        $legacyCustomHtaccessFile = ETC_DIR . 'htaccess.custom.php';

        if (!file_exists($legacyCustomHtaccessFile)) {
            return;
        }

        if (file_exists(self::CUSTOM_HTACCESS_FILE_PATH)) {
            return;
        }

        $this->createCustomHtaccessFile(file_get_contents($legacyCustomHtaccessFile));
        unlink($legacyCustomHtaccessFile);
    }

    private function createCustomHtaccessFile(string $content): void
    {
        $customHtaccessDir = dirname(self::CUSTOM_HTACCESS_FILE_PATH);

        if (!is_dir($customHtaccessDir)) {
            mkdir($customHtaccessDir, 0755, true);
        }

        file_put_contents(self::CUSTOM_HTACCESS_FILE_PATH, $content);
    }
}
