<?php

declare(strict_types=1);

/**
 * This file is part of CodeIgniter 4 framework.
 *
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace CodeIgniter\Test;

use PHPUnit\Framework\Attributes\Group;

/**
 * This test confirms that the bootstrap.php
 * will set the correct FCPATH regardless of the current directory
 *
 * It writes a file in the temp directory that loads the bootstrap file
 * then compares its echo FCPATH; to the correct FCPATH returned
 * from correctFCPATH();
 *
 * @internal
 */
#[Group('Others')]
final class BootstrapFCPATHTest extends CIUnitTestCase
{
    private string $currentDir = __DIR__;
    private string $dir1       = '/tmp/dir1';
    private string $file1      = '/tmp/dir1/testFile.php';

    protected function setUp(): void
    {
        parent::setUp();
        $this->deleteFiles();
        $this->deleteDirectories();
        $this->buildDirectories();
        $this->writeFiles();
    }

    protected function tearDown(): void
    {
        parent::tearDown();
        $this->deleteFiles();
        $this->deleteDirectories();
    }

    public function testSetFCPATH(): void
    {
        $result1     = $this->readOutput($this->file1);
        $correctPath = $this->correctFCPATH();
        $this->assertSame($correctPath, $result1);
    }

    private function correctFCPATH(): string
    {
        return realpath(__DIR__ . '/../../../public') . DIRECTORY_SEPARATOR;
    }

    private function buildDirectories(): void
    {
        mkdir($this->dir1, 0777, true);
    }

    private function deleteDirectories(): void
    {
        // these need to be executed in reverse order: dir 2 in inside dir1
        if (is_dir($this->dir1)) {
            rmdir($this->dir1);
        }
    }

    private function writeFiles(): void
    {
        file_put_contents($this->file1, $this->fileContents());
        chmod($this->file1, 0777);
    }

    private function deleteFiles(): void
    {
        if (is_file($this->file1)) {
            unlink($this->file1);
        }
    }

    private function fileContents(): string
    {
        $fileContents = '';
        $fileContents .= '<?php' . PHP_EOL;
        $fileContents .= "define('HOMEPATH', '" . $this->currentDir . "' . '/../../../');" . PHP_EOL;
        $fileContents .= "define('CONFIGPATH', '" . $this->currentDir . "' . '/../../../app/Config/');" . PHP_EOL;
        $fileContents .= "define('PUBLICPATH', '" . $this->currentDir . "' . '/../../../public/');" . PHP_EOL;
        $fileContents .= "include_once '" . $this->currentDir . "' . '/../../../vendor/autoload.php';" . PHP_EOL;
        $fileContents .= "include_once '" . $this->currentDir . "' . '/../../../system/Test/bootstrap.php';" . PHP_EOL;
        $fileContents .= '// return value of FCPATH' . PHP_EOL;

        return $fileContents . 'echo FCPATH;' . PHP_EOL;
    }

    private function readOutput(string $file): false|string
    {
        ob_start();
        system('php -f ' . $file);

        return ob_get_clean();
    }
}
