<?php

declare(strict_types=1);

namespace App\Core;

use Dotenv\Dotenv;

class Application
{
    private static self $instance;

    private Router $router;
    private Request $request;
    private Response $response;
    private string $basePath;

    public function __construct(string $basePath)
    {
        self::$instance = $this;
        $this->basePath = $basePath;

        $this->loadEnvironment();
        $this->startSession();

        $this->request = new Request();
        $this->response = new Response();
        $this->router = new Router($this->request, $this->response);
    }

    public static function instance(): self
    {
        return self::$instance;
    }

    public function run(): void
    {
        echo $this->router->resolve();
    }

    public function router(): Router
    {
        return $this->router;
    }

    public function request(): Request
    {
        return $this->request;
    }

    public function response(): Response
    {
        return $this->response;
    }

    public function basePath(string $path = ''): string
    {
        return $this->basePath . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : '');
    }

    public function publicBasePath(): string
    {
        $scriptName = str_replace('\\', '/', (string) ($_SERVER['SCRIPT_NAME'] ?? ''));
        $directory = rtrim(str_replace('\\', '/', dirname($scriptName)), '/');

        return $directory === '/' || $directory === '.' ? '' : $directory;
    }

    private function loadEnvironment(): void
    {
        if (file_exists($this->basePath . '/.env')) {
            Dotenv::createImmutable($this->basePath)->safeLoad();
        }
    }

    private function startSession(): void
    {
        if (session_status() === PHP_SESSION_NONE) {
            $sessionPath = $this->basePath . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'sessions';

            if (!is_dir($sessionPath)) {
                mkdir($sessionPath, 0775, true);
            }

            if (!is_writable($sessionPath)) {
                $sessionPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mozcursos_sessions';

                if (!is_dir($sessionPath)) {
                    mkdir($sessionPath, 0775, true);
                }
            }

            session_save_path($sessionPath);

            $sessionName = session_name();
            $incomingSessionId = (string) ($_COOKIE[$sessionName] ?? '');

            if ($incomingSessionId !== '') {
                $sessionFile = $sessionPath . DIRECTORY_SEPARATOR . 'sess_' . $incomingSessionId;

                if (is_file($sessionFile) && !is_writable($sessionFile)) {
                    session_id(bin2hex(random_bytes(16)));
                }
            }

            session_start();
        }
    }
}
