<?php

declare(strict_types=1);

function statBasePath(): string
{
    static $basePath = null;

    if (is_string($basePath)) {
        return $basePath;
    }

    $scriptName = $_SERVER['SCRIPT_NAME'] ?? '';

    if (!is_string($scriptName)) {
        $basePath = '';
        return $basePath;
    }

    $scriptName = str_replace('\\', '/', $scriptName);

    if (
        $scriptName === ''
        || $scriptName[0] !== '/'
        || preg_match('/[\x00-\x1F\x7F]/', $scriptName) === 1
    ) {
        $basePath = '';
        return $basePath;
    }

    $dir = rtrim(str_replace('\\', '/', dirname($scriptName)), '/');

    if ($dir === '' || $dir === '.' || $dir === '/') {
        $basePath = '';
        return $basePath;
    }

    $sections = ['realtime', 'performance', 'clicks', 'postback'];

    foreach ($sections as $section) {
        $legacySuffix = '/statistics/' . $section;
        $directSuffix = '/' . $section;

        if (substr($dir, -strlen($legacySuffix)) === $legacySuffix) {
            $dir = substr($dir, 0, -strlen($legacySuffix));
            break;
        }

        if (substr($dir, -strlen($directSuffix)) === $directSuffix) {
            $dir = substr($dir, 0, -strlen($directSuffix));
            break;
        }
    }

    $dir = rtrim($dir, '/');

    if ($dir === '' || $dir === '.' || $dir === '/') {
        $basePath = '';
        return $basePath;
    }

    $basePath = $dir;

    return $basePath;
}

function statUrl(string $path): string
{
    $path = trim($path);

    if ($path === '') {
        return statBasePath() . '/';
    }

    if (!statIsSafeAppPath($path, true)) {
        return statBasePath() . '/';
    }

    if ($path[0] !== '/') {
        $path = '/' . $path;
    }

    return statBasePath() . $path;
}

function statAssetUrl(string $path): string
{
    $path = trim($path);

    if ($path === '') {
        return '';
    }

    if ($path[0] !== '/') {
        $path = '/' . $path;
    }

    if (!statIsSafeAppPath($path, false)) {
        return '';
    }

    if (
        !preg_match('#\A/(dist|fonts)/[A-Za-z0-9._/-]+\z#', $path)
        && !in_array($path, ['/favicon.ico', '/robots.txt'], true)
    ) {
        return '';
    }

    return statUrl($path);
}

function statH(string $value): string
{
    return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

function statIsSafeAppPath(string $path, bool $allowQueryString): bool
{
    if ($path === '') {
        return false;
    }

    if (preg_match('/[\x00-\x1F\x7F]/', $path) === 1) {
        return false;
    }

    if (str_contains($path, '\\')) {
        return false;
    }

    if (str_contains($path, '://') || str_starts_with($path, '//')) {
        return false;
    }

    if (!$allowQueryString && (str_contains($path, '?') || str_contains($path, '#'))) {
        return false;
    }

    $pathOnly = $path;
    $queryPos = strpos($pathOnly, '?');

    if ($queryPos !== false) {
        if (!$allowQueryString) {
            return false;
        }

        $pathOnly = substr($pathOnly, 0, $queryPos);
    }

    $fragmentPos = strpos($pathOnly, '#');

    if ($fragmentPos !== false) {
        return false;
    }

    if ($pathOnly === '') {
        return false;
    }

    if ($pathOnly[0] !== '/') {
        $pathOnly = '/' . $pathOnly;
    }

    if (str_contains($pathOnly, '//')) {
        return false;
    }

    $segments = explode('/', $pathOnly);

    foreach ($segments as $segment) {
        if ($segment === '..') {
            return false;
        }

        if (preg_match('/%2e|%2f|%5c/i', $segment) === 1) {
            return false;
        }
    }

    return true;
}
