<?php
/**
 * AegisOne Engineering — Функции управления документацией в Markdown
 *
 * Обеспечивает:
 *  - Автоматическое обнаружение .md-файлов в service/docs/
 *  - Разграничение доступа по ролям (owner — всё, engineer — только разрешённое)
 *  - Хранение прав в JSON-файле service/permissions/docs_permissions.json
 */

define('DOCS_DIR', __DIR__ . '/../docs');
define('DOCS_PERMISSIONS_FILE', __DIR__ . '/../permissions/docs_permissions.json');

/**
 * Сканирует папку docs/ и возвращает массив документов.
 * Автоматически добавляет новые файлы в файл прав (если их там нет).
 *
 * @return array Массив документов: [['slug'=>'...', 'title'=>'...', 'filename'=>'...'], ...]
 */
function get_docs_list(): array
{
    if (!is_dir(DOCS_DIR)) {
        return [];
    }

    $files = glob(DOCS_DIR . '/*.md');
    if ($files === false || empty($files)) {
        return [];
    }

    $docs = [];
    $permissions = load_permissions();

    foreach ($files as $path) {
        $filename = basename($path);
        $slug     = doc_slug($filename);
        $title    = doc_title($slug, $filename);

        // Автоматически добавляем новый документ в права, если его ещё нет
        if (!isset($permissions[$slug])) {
            $permissions[$slug] = [
                'title'    => $title,
                'filename' => $filename,
                'sort_order' => count($permissions),
                'engineer' => false,
            ];
        }

        // Миграция: старый boolean → новый array permissions
        if (isset($permissions[$slug]['engineer']) && !isset($permissions[$slug]['permissions'])) {
            $permissions[$slug]['permissions'] = [
                'engineer' => [
                    'view' => !empty($permissions[$slug]['engineer']),
                    'edit' => false,
                    'cancel' => false,
                ]
            ];
        }

        // Если файл на диске отличается от сохранённого — обновляем
        if ($permissions[$slug]['filename'] !== $filename) {
            $permissions[$slug]['filename'] = $filename;
        }

        $docs[] = [
            'slug'     => $slug,
            'title'    => $permissions[$slug]['title'],
            'filename' => $filename,
            'sort_order' => $permissions[$slug]['sort_order'] ?? 0,
        ];
    }

    // Сохраняем, если были добавлены новые
    save_permissions($permissions);

    // Сортировка по sort_order (ручная), затем по title
    usort($docs, function($a, $b) {
        $soA = $a['sort_order'] ?? 0;
        $soB = $b['sort_order'] ?? 0;
        if ($soA !== $soB) return $soA - $soB;
        return strcmp($a['title'], $b['title']);
    });

    return $docs;
}

/**
 * Возвращает содержимое .md-файла по слагу.
 * Ищет файл по slug, сканируя директорию (не полагается на сохранённое имя).
 *
 * @param string $slug Слаг документа
 * @return string|null Содержимое файла или null, если не найден
 */
function get_doc_content(string $slug): ?string
{
    $permissions = load_permissions();
    if (!isset($permissions[$slug])) {
        return null;
    }

    // Сначала пробуем сохранённое имя файла
    $savedFilename = $permissions[$slug]['filename'];
    $path = DOCS_DIR . '/' . $savedFilename;
    if (file_exists($path)) {
        $content = file_get_contents($path);
        return $content !== false ? $content : null;
    }

    // Если не нашли — ищем по slug среди всех .md файлов
    $files = glob(DOCS_DIR . '/*.md');
    if ($files === false) return null;

    foreach ($files as $filePath) {
        $fn = basename($filePath);
        $fSlug = doc_slug($fn);
        if ($fSlug === $slug) {
            // Обновляем сохранённое имя
            $permissions[$slug]['filename'] = $fn;
            save_permissions($permissions);
            $content = file_get_contents($filePath);
            return $content !== false ? $content : null;
        }
    }

    return null;
}

/**
 * Преобразует md-заголовки и ссылки в HTML.
 * Простейший парсер для базовой читаемости.
 *
 * @param string $markdown Исходный Markdown
 * @return string HTML
 */
function render_markdown_simple(string $markdown): string
{
    $html = htmlspecialchars($markdown, ENT_NOQUOTES, 'UTF-8');

    // Заголовки h1-h3
    $html = preg_replace('/^### (.+)$/m', '<h3>$1</h3>', $html);
    $html = preg_replace('/^## (.+)$/m', '<h2>$1</h2>', $html);
    $html = preg_replace('/^# (.+)$/m', '<h1>$1</h1>', $html);

    // Жирный и курсив
    $html = preg_replace('/\*\*(.+?)\*\*/', '<strong>$1</strong>', $html);
    $html = preg_replace('/\*(.+?)\*/', '<em>$1</em>', $html);

    // Списки
    $html = preg_replace('/^- (.+)$/m', '<li>$1</li>', $html);
    $html = preg_replace('/(<li>.*<\/li>)/s', '<ul>$1</ul>', $html);

    // Таблицы — группируем строки с | в блоки <table>
    $lines = explode("\n", $html);
    $in_table = false;
    $sep_skipped = false;
    $table_lines = [];
    foreach ($lines as $line) {
        $trimmed = trim($line);
        if (preg_match('/^\|.+\|$/', $trimmed)) {
            if (!$in_table) {
                $table_lines[] = '<table>';
                $in_table = true;
                $sep_skipped = false;
            }
            if (preg_match('/^\|[-:\s]+\|$/', $trimmed)) {
                $sep_skipped = true;
                continue;
            }
            $inner = substr($trimmed, 1, -1);
            $cells = array_map('trim', explode('|', $inner));
            $tag = $sep_skipped ? 'th' : 'td';
            $sep_skipped = false;
            $table_lines[] = "<tr><$tag>" . implode("</$tag><$tag>", $cells) . "</$tag></tr>";
        } else {
            if ($in_table) {
                $table_lines[] = '</table>';
                $in_table = false;
            }
            $sep_skipped = false;
            $table_lines[] = $line;
        }
    }
    if ($in_table) {
        $table_lines[] = '</table>';
    }
    $html = implode("\n", $table_lines);

    // Ссылки
    $html = preg_replace('/\[(.+?)\]\((.+?)\)/', '<a href="$2" target="_blank">$1</a>', $html);

    // Абзацы
    $paragraphs = explode("\n\n", $html);
    $html = '';
    foreach ($paragraphs as $p) {
        $p = trim($p);
        if ($p === '') continue;
        if (strpos($p, '<h') === 0 || strpos($p, '<ul') === 0 || strpos($p, '<tr') === 0 || strpos($p, '<th') === 0 || strpos($p, '<table') === 0) {
            $html .= $p . "\n";
        } elseif (strpos($p, '<li') === 0) {
            $html .= $p . "\n";
        } else {
            $html .= '<p>' . nl2br($p) . "</p>\n";
        }
    }

    return $html;
}

/**
 * Возвращает slug из имени файла (архитектура.md → arkhitektura).
 */
function doc_slug(string $filename): string
{
    $slug = pathinfo($filename, PATHINFO_FILENAME);
    // Транслитерация кириллицы в латиницу для URL
    $converted = transliterate($slug);
    return preg_replace('/[^a-z0-9_-]/', '', strtolower($converted));
}

/**
 * Транслитерация кириллицы → латиница.
 */
function transliterate(string $text): string
{
    $map = [
        'а'=>'a','б'=>'b','в'=>'v','г'=>'g','д'=>'d','е'=>'e','ё'=>'yo','ж'=>'zh',
        'з'=>'z','и'=>'i','й'=>'y','к'=>'k','л'=>'l','м'=>'m','н'=>'n','о'=>'o',
        'п'=>'p','р'=>'r','с'=>'s','т'=>'t','у'=>'u','ф'=>'f','х'=>'kh','ц'=>'ts',
        'ч'=>'ch','ш'=>'sh','щ'=>'shch','ъ'=>'','ы'=>'y','ь'=>'','э'=>'e','ю'=>'yu',
        'я'=>'ya','А'=>'A','Б'=>'B','В'=>'V','Г'=>'G','Д'=>'D','Е'=>'E','Ё'=>'Yo',
        'Ж'=>'Zh','З'=>'Z','И'=>'I','Й'=>'Y','К'=>'K','Л'=>'L','М'=>'M','Н'=>'N',
        'О'=>'O','П'=>'P','Р'=>'R','С'=>'S','Т'=>'T','У'=>'U','Ф'=>'F','Х'=>'Kh',
        'Ц'=>'Ts','Ч'=>'Ch','Ш'=>'Sh','Щ'=>'Shch','Ъ'=>'','Ы'=>'Y','Ь'=>'','Э'=>'E',
        'Ю'=>'Yu','Я'=>'Ya',' '=>'-','_'=>'-',
    ];
    return strtr($text, $map);
}

/**
 * Формирует человекочитаемый заголовок из слага.
 * architecture → Архитектура
 */
function doc_title(string $slug, string $filename = ''): string
{
    // обратная транслитерация для некоторых известных слагов
    $known = [
        'owner'                     => 'Owner',
        'seo'                       => 'SEO',
        'sla'                       => 'SLA',
        'kpi-inzhenerov'            => 'KPI инженеров',
        'avtomaticheskaya-sistema-shs' => 'Автоматическая система SHS',
        'oprosnik-raschet'          => 'Опросник-расчёт',
        'arkhitektura-kompanii'     => 'Архитектура компании',
        'kontent-plan'              => 'Контент план',
        'kp-i-struktura-audita'     => 'КП и структура аудита',
        'utp-i-kp'                  => 'УТП и КП',
        'arkhetiktura-brenda'       => 'Архетиктура бренда',
        'marketing'                 => 'Маркеттинг',
        'skripty-prodazh'           => 'Скрипты продаж',
        'osnova'                    => 'Основа',
        'dokazatelnaya-ekspertiza'  => 'Доказательная экспертиза',
        'voronki-telegram-i-crm'    => 'Воронки телеграм и CRM',
        'voronka'                   => 'Воронка',
        'sayt-i-upakovka'           => 'Сайт и упаковка',
        'dashboard-tekhnika'        => 'Дашборд техника',
        'dashboard-inzhenera'       => 'Дашборд инженера',
        'blog'                      => 'Блог',
        'tsifrovaya-model-obshchaya' => 'Цифровая модель общая',
    ];

    if (isset($known[$slug])) {
        return $known[$slug];
    }

    // Если есть имя файла — используем его без .md
    if ($filename !== '') {
        return pathinfo($filename, PATHINFO_FILENAME);
    }

    return strtr($slug, ['-' => ' ', '_' => ' ']);
}

/**
 * Загружает JSON-файл прав доступа.
 *
 * @return array
 */
function load_permissions(): array
{
    if (!file_exists(DOCS_PERMISSIONS_FILE)) {
        return [];
    }

    $json = file_get_contents(DOCS_PERMISSIONS_FILE);
    $data = json_decode($json, true);

    return is_array($data) ? $data : [];
}

/**
 * Сохраняет JSON-файл прав доступа.
 *
 * @param array $permissions
 * @return bool
 */
function save_permissions(array $permissions): bool
{
    $dir = dirname(DOCS_PERMISSIONS_FILE);
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }

    return file_put_contents(
        DOCS_PERMISSIONS_FILE,
        json_encode($permissions, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
    ) !== false;
}

/**
 * Проверяет, разрешён ли документ для роли engineer.
 *
 * @param string $slug Слаг документа
 * @return bool
 */
function is_doc_allowed_for_engineer(string $slug): bool
{
    $permissions = load_permissions();
    if (!isset($permissions[$slug])) return false;
    $p = $permissions[$slug];
    // Поддержка старого формата (boolean) и нового (array)
    if (is_array($p) && isset($p['permissions'])) {
        return !empty($p['permissions']['engineer']['view']);
    }
    return !empty($p['engineer']);
}

/**
 * Проверяет конкретное право инженера для документа.
 *
 * @param string $slug Слаг документа
 * @param string $action Действие: view, edit, cancel
 * @return bool
 */
function is_engineer_allowed(string $slug, string $action): bool
{
    $permissions = load_permissions();
    if (!isset($permissions[$slug])) return false;
    $p = $permissions[$slug];
    if (is_array($p) && isset($p['permissions']['engineer'])) {
        return !empty($p['permissions']['engineer'][$action]);
    }
    // Backward compat
    if ($action === 'view') return !empty($p['engineer']);
    return false;
}

/**
 * Возвращает список документов, доступных для указанной роли.
 *
 * @param string $role Роль пользователя (owner|engineer|technician)
 * @return array
 */
function get_allowed_docs(string $role): array
{
    $all = get_docs_list();

    if ($role === 'owner') {
        return $all;
    }

    if ($role === 'engineer') {
        return array_values(array_filter($all, function($d) {
            return is_doc_allowed_for_engineer($d['slug']);
        }));
    }

    // technician — нет доступа к документам
    return [];
}
