<?php
// /helpers.php

function formatBytes($bytes, $precision = 2) {
    $units = ['Б', 'КБ', 'МБ', 'ГБ', 'ТБ'];
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    $bytes /= pow(1024, $pow);
    return round($bytes, $precision) . ' ' . $units[$pow];
}

// Здесь можно добавить другие вспомогательные функции
function isImage($filename) {
    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    return in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp']);
}

function getFileIcon($filename) {
    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    $icons = [
        'pdf' => '📕',
        'doc' => '📘',
        'docx' => '📘',
        'xls' => '📗',
        'xlsx' => '📗',
        'zip' => '📦',
        'rar' => '📦',
        'mp3' => '🎵',
        'mp4' => '🎬',
    ];
    return $icons[$ext] ?? '📄';
}

function addButtonToHeaderSide(&$headerSide, $icon, $text, $href) {
    $content = ($icon ?? '') . ' ' . htmlspecialchars($text);
    if ($href === 'submit') {
        $content = "<button class=\"btn\" type=\"submit\" form=\"formId\">$content</button>";
    }
    else {
       $content = "<a class=\"btn\" href=\"" . htmlspecialchars($href) . "\">$content</a>";
    }
    $headerSide[] = $content;
}

/**
 * Конвертирует текст с markdown-разметкой в HTML.
 * Полученный текст сразу экранируется, чтобы любые тэги заменить на спецсимволы, и они,
 * при отправке в браузер, просто отображались как символы тэгов, а не исполнялись как код.
 * Исполняемые тэги будут только те, что функция сама подставит в процессе конвертации
 * markdown-разметки в тэги HTML.
 */
function textToHtml($text) {
	// Экранируем текст
	$text = htmlspecialchars($text);
	
	// Заменяем блоки кода ```text``` на ###CODE_BLOCKn### в тексте, записываем html-тэги в отдельный массив
	$codeBlocks = [];
	$text = preg_replace_callback('/```(.*?)```/s', function($matches) use (&$codeBlocks) {
		static $counter = 0;
		$placeholder = "###CODE_BLOCK_" . $counter . "###";
		
		// Удаляем пустые строки (включая строки с пробелами) в начале и конце
		$codeContent = preg_replace('/^\s+|\s+$/', '', $matches[1]);
		
		// Включаем буферизацию
		ob_start();
		// Подключаем шаблон, код будет доступен через $codeContent
		include __DIR__ . '/templates/code_block.php';
		$codeBlocks[$placeholder] = ob_get_clean();
		
		$counter++;
		return $placeholder;
	}, $text);
	
	// Также заменяем тэги изображений вида ![name](link) отдельно
	$images = [];
	$text = preg_replace_callback('/!\[([^\]]*)\]\(([^)]+)\)/', function($matches) use (&$images) {
		static $counter = 0;
		$placeholder = "###IMAGE_" . $counter . "###";
		
		$imageUrl = $matches[2];
		
		// Включаем буферизацию
		ob_start();
		// Подключаем шаблон, изображение будет доступно через $imageUrl
		include __DIR__ . '/templates/image_block.php';
		$images[$placeholder] = ob_get_clean();
		
		//$images[$placeholder] = '<img src="' . htmlspecialchars($matches[2]) . '" alt="' . htmlspecialchars($matches[1]) . '">';
		$counter++;
		return $placeholder;
	}, $text);
	
	// Теперь обрабатываем остальной текст построчно
	$lines = explode("\n", $text);
	
	$result = [];
	$inList = false;
	$inQuote = false;
	
	foreach ($lines as $line) {
		$replaceText = '';
		
		// Цитаты
		if (preg_match('/^(&gt;\ )(?=[^\s])/m', $line, $matches)) {
			$inQuote = true;
			$replaceText = substr_replace(trim($line), '<blockquote>', 0, strlen($matches[1]));
		}
		// Пустая строка (закрывает списки и цитаты, если они были)
		else if (trim($line) === '') {
			if ($inList) {
				$replaceText = '</ul>';
				$inList = false;
			}
			else if ($inQuote) {
				$replaceText = '</blockquote>';
				$inQuote = false;
			}
			else {
				//$replaceText = '<p>&nbsp;</p>';
			}
		}
		// Заголовки
		else if (preg_match('/^(#{1,6})\s+(.*)$/', $line, $matches)) {
			$level = strlen($matches[1]);
			$replaceText = '<h' . $level . '>' . $matches[2] . '</h' . $level . '>';
		}
		// Горизонтальная линия
		else if (trim($line) === '---') {
			$replaceText = '<hr>';
		}
		// Маркированный список (*, -, +)
		else if (preg_match('/^[\*\-\+]\s+(.*)$/', $line, $matches)) {
			if (!$inList) {
				$inList = true;
				$replaceText = '<ul>';
			}
			$replaceText .= '<li>' . $matches[1] . '</li>';
		}
		
		if ($replaceText !== '') {
			$result[] = formatInline($replaceText);
		}
		else {
			$result[] = formatInline(trim($line));
		}
		// В конце строки символ перехода на новую строку
		$result[] .= '<br>';
	}
	
	// Закрываем последний список, если он был
	if ($inList) {
		$result[] = '</ul>';
	}
	if ($inQuote) {
		$result[] = '</blockquote>';
	}
	
	$text = implode("\n", $result);
	
	// Заменяем плейсхолдеры изображений
	$text = preg_replace_callback('/###IMAGE_(\d+)###/', function($matches) use (&$images) {
		if (isset($images[$matches[0]])) {
			return $images[$matches[0]];
		};
	}, $text);
	
	// Заменяем плейсхолдеры блоков кода
	$text = preg_replace_callback('/###CODE_BLOCK_(\d+)###/', function($matches) use (&$codeBlocks) {
		if (isset($codeBlocks[$matches[0]])) {
			return $codeBlocks[$matches[0]];
		};
	}, $text);
	
	return $text;
}

/**
 * Форматирование inline-элементов (жирный, курсив, ссылки и т.д.)
 */
function formatInline($text) {
    // Жирный и курсив
    $text = preg_replace('/\*\*\*(.*?)\*\*\*/', '<strong><em>$1</em></strong>', $text);
    $text = preg_replace('/\*\*(.*?)\*\*/', '<strong>$1</strong>', $text);
    $text = preg_replace('/\*(.*?)\*/', '<em>$1</em>', $text);
    
    // Ссылки [текст](url)
    $text = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $text);
    
    // Изображения ![alt](url)
    $text = preg_replace('/!\[([^\]]*)\]\(([^)]+)\)/', '<img src="$2" alt="$1">', $text);
    
    // Код внутри строки
    $text = preg_replace('/`([^`]+)`/', '<code>$1</code>', $text);
    
    return $text;
}

function exitlog($data) {
    echo "<h3>Отладка</h3>";
    echo "<pre>";
    echo "DATA: " . ($data ?? 'НЕТ') . "\n";
    echo "</pre>";
    exit; // Важно! Останавливаем выполнение
}

/**
 * Работает в связке с flush_console_log().
 * flush_console_log() должна вызываться в самом конце обработки HTML страницы,
 * то есть перед закрывающим </body> в главном шаблоне сайта, и тогда
 * consolog() можно использовать в любом месте кода даже с редиректами
 */
function consolog($data) {
    // Сохраняем сообщения в сессию
    if (!isset($_SESSION['consolog'])) {
        $_SESSION['consolog'] = [];
    }
    
    $_SESSION['consolog'][] = [
        'data' => $data,
        'time' => date('H:i:s')
    ];
    
    // Ограничиваем размер (чтобы сессия не распухала)
    if (count($_SESSION['consolog']) > 20) {
        array_shift($_SESSION['consolog']);
    }
}

// Функция для вывода всех накопленных сообщений (вызывать в layout.php перед </body>)
function flush_console_log() {
    if (isset($_SESSION['consolog']) && !empty($_SESSION['consolog'])) {
        echo "<script>\n";
        echo "console.group('🐘 PHP Console');\n";
        foreach ($_SESSION['consolog'] as $log) {
            $json = json_encode($log['data'], JSON_UNESCAPED_UNICODE);
            echo "console.log('[{$log['time']}]', {$json});\n";
        }
        echo "console.groupEnd();\n";
        echo "</script>\n";
        
        // Очищаем после вывода
        unset($_SESSION['consolog']);
    }
}
