<?php

class Navigation
{
    private array $config;
    private ?PluginAPIInterface $api = null;

    public function __construct()
    {
        $this->config = [
            'title' => 'Navigatie',
            'viewable' => true,
            'type' => 'content',
        ];
    }

    public function setAPI(PluginAPIInterface $api): void
    {
        $this->api = $api;
    }

    public function getConfig(): array
    {
        return $this->config;
    }

    public function setConfig(array $config): void
    {
        $this->config = array_merge($this->config, $config);
    }

    /**
     * Get the path to this plugin's CSS file (relative to web root).
     */
    public function getCssUrl(): string
    {
        return '/plugins/Navigation/assets/css/navigation.css';
    }

    /**
     * Generate sidebar navigation.
     * Detects whether we're on a guide page or content page and builds nav accordingly.
     */
    public function getSidebarContent(): string
    {
        $isGuide = isset($_GET['guide']) || ($_GET['page'] ?? '') === 'guide';
        $isAdminGuide = isset($_GET['route']) && $_GET['route'] === 'guide';
        $isAdmin = isset($_GET['route']);
        $lang = $_GET['lang'] ?? ($this->api ? $this->api->getCurrentLanguage() : 'nl');
        $currentPage = $_GET['page'] ?? '';

        if ($isGuide || $isAdminGuide) {
            return $this->buildGuideNav($lang, $currentPage, $isAdminGuide);
        }

        // Content navigation
        if ($isAdmin) {
            return '';
        }
        return $this->buildContentNav($lang, $currentPage);
    }

    /**
     * Build navigation for the guide section.
     */
    private function buildGuideNav(string $lang, string $currentPage, bool $isAdmin): string
    {
        $guideRoot = dirname(__DIR__, 2) . '/guide/' . $lang;
        if (!is_dir($guideRoot)) {
            return '';
        }

        // Fix: /nl/guide sets page='guide', treat as empty
        if ($currentPage === 'guide') {
            $currentPage = '';
        }

        return $this->buildNav($guideRoot, '', $currentPage, $isAdmin, 'guide', $lang);
    }

    /**
     * Build navigation for the content section.
     */
    private function buildContentNav(string $lang, string $currentPage): string
    {
        $contentRoot = dirname(__DIR__, 2) . '/content';
        if (!is_dir($contentRoot)) {
            return '';
        }

        // Normalize current page: remove extension
        $currentPage = preg_replace('/\.(md|php|html)$/', '', $currentPage);

        return $this->buildNav($contentRoot, '', $currentPage, false, 'content', $lang);
    }

    /**
     * Recursively build navigation from a directory structure.
     *
     * @param string $dir Current directory
     * @param string $relPath Relative path from root
     * @param string $currentPage Current page path
     * @param bool $isAdmin Whether this is admin context
     * @param string $mode 'guide' or 'content'
     * @param string $lang Current language
     * @param int $depth Nesting depth (0 = top level)
     */
    private function buildNav(string $dir, string $relPath, string $currentPage, bool $isAdmin, string $mode, string $lang, int $depth = 0): string
    {
        $items = [];
        $entries = scandir($dir);
        // Sort alphabetically (case-insensitive)
        natcasesort($entries);

        foreach ($entries as $entry) {
            if ($entry === '.' || $entry === '..' || $entry === 'assets' || $entry === 'index.md') {
                continue;
            }
            // Skip hidden files/folders (starting with -)
            if ($entry[0] === '-' || $entry[0] === '.') {
                continue;
            }
            // Skip non-content files in content mode
            if ($mode === 'content' && is_file($dir . '/' . $entry)) {
                $ext = pathinfo($entry, PATHINFO_EXTENSION);
                if (!in_array($ext, ['md', 'php', 'html'])) {
                    continue;
                }
            }

            $fullPath = $dir . '/' . $entry;
            $itemRelPath = $relPath ? $relPath . '/' . $entry : $entry;

            if (is_dir($fullPath)) {
                $parentMd = $dir . '/' . $entry . '.md';
                $title = file_exists($parentMd) ? $this->getTitleFromFile($parentMd) : $this->formatTitle($entry);

                $pageRef = $relPath ? $relPath . '/' . $entry : $entry;
                $url = $this->buildUrl($pageRef, $lang, $isAdmin, $mode);
                $children = $this->buildNav($fullPath, $itemRelPath, $currentPage, $isAdmin, $mode, $lang, $depth + 1);

                // Only show directories that have children or a parent .md
                if (empty($children) && !file_exists($parentMd)) {
                    continue;
                }

                $items[] = [
                    'title' => $title,
                    'url' => $url,
                    'active' => $this->isActive($pageRef, $currentPage, $mode),
                    'children' => $children,
                    'has_children' => !empty($children),
                ];
            } else {
                $ext = pathinfo($entry, PATHINFO_EXTENSION);
                if (!in_array($ext, ['md', 'php', 'html'])) {
                    continue;
                }

                $slug = pathinfo($entry, PATHINFO_FILENAME);
                // Skip language-prefixed files (e.g. nl.pagina.md)
                $langCodes = $this->getLanguageCodes();
                foreach ($langCodes as $lc) {
                    if (strpos($slug, $lc . '.') === 0) {
                        $slug = substr($slug, strlen($lc) + 1);
                        break;
                    }
                }
                // Skip if this is a parent .md that has a matching directory
                if (is_dir($dir . '/' . $slug)) {
                    continue;
                }

                $pageRef = $relPath ? $relPath . '/' . $slug : $slug;
                $url = $this->buildUrl($pageRef, $lang, $isAdmin, $mode);

                $items[] = [
                    'title' => $this->getTitleFromFile($fullPath),
                    'url' => $url,
                    'active' => $this->isActive($pageRef, $currentPage, $mode),
                    'children' => '',
                    'has_children' => false,
                ];
            }
        }

        return $this->renderNav($items, $depth);
    }

    /**
     * Build the URL for a page.
     */
    private function buildUrl(string $pageRef, string $lang, bool $isAdmin, string $mode): string
    {
        if ($mode === 'guide') {
            if ($isAdmin) {
                return '/admin/guide?page=' . urlencode($pageRef) . '&lang=' . urlencode($lang);
            }
            return '/' . urlencode($lang) . '/guide?page=' . urlencode($pageRef);
        }
        // Content mode
        return '/' . urlencode($lang) . '/' . urlencode($pageRef);
    }

    /**
     * Check if a nav item is the current page.
     */
    private function isActive(string $pageRef, string $currentPage, string $mode): bool
    {
        if ($mode === 'guide' && $currentPage === 'guide') {
            $currentPage = '';
        }
        $currentPage = preg_replace('/\.(md|php|html)$/', '', $currentPage);
        return $pageRef === $currentPage;
    }

    /**
     * Get available language codes.
     */
    private function getLanguageCodes(): array
    {
        return ['nl', 'en', 'de', 'fr'];
    }

    /**
     * Format a slug into a readable title.
     */
    private function formatTitle(string $slug): string
    {
        $title = str_replace('-', ' ', $slug);
        $title = ucfirst($title);
        return $title;
    }

    /**
     * Extract the H1 title from a markdown/PHP/HTML file.
     * Falls back to formatTitle() if no H1 is found.
     */
    private function getTitleFromFile(string $filePath): string
    {
        if (!file_exists($filePath)) {
            return '';
        }

        $content = file_get_contents($filePath);
        // Match first H1: # Title
        if (preg_match('/^#\s+(.+)$/m', $content, $matches)) {
            return trim($matches[1]);
        }

        $slug = pathinfo($filePath, PATHINFO_FILENAME);
        return $this->formatTitle($slug);
    }

    /**
     * Render the navigation items as HTML.
     *
     * @param array $items Navigation items
     * @param int $depth Nesting depth (0 = top level)
     */
    private function renderNav(array $items, int $depth = 0): string
    {
        if (empty($items)) {
            return '';
        }

        $subClass = $depth > 0 ? ' nav-sub' : '';
        $html = '<ul class="list-unstyled nav-plugin' . $subClass . '">';
        foreach ($items as $item) {
            $activeClass = $item['active'] ? ' active' : '';
            $parentClass = $item['has_children'] ? ' nav-parent' : '';
            $html .= '<li class="nav-plugin-item">';
            $html .= '<a href="' . htmlspecialchars($item['url'], ENT_QUOTES, 'UTF-8') . '" class="nav-plugin-link' . $activeClass . $parentClass . '">';
            if ($item['has_children']) {
                $html .= '<i class="bi bi-folder-fill nav-plugin-icon"></i> ';
            } else {
                $html .= '<i class="bi bi-file-earmark nav-plugin-icon"></i> ';
            }
            $html .= htmlspecialchars($item['title'], ENT_QUOTES, 'UTF-8');
            $html .= '</a>';

            if ($item['has_children']) {
                $html .= $item['children'];
            }

            $html .= '</li>';
        }
        $html .= '</ul>';

        return $html;
    }
}