<?php

require_once APP_ROOT . '/models/Article.php';

class SitemapController
{
    /**
     * Map static page paths to their corresponding view files (relative to APP_ROOT).
     * Used to derive a real <lastmod> from filemtime() instead of today's date.
     */
    private const STATIC_PAGE_VIEWS = [
        ''                => '/views/auth/login.php',
        'login'           => '/views/auth/login.php',
        'register'        => '/views/auth/register.php',
        'support'         => '/views/pages/support.php',
        'contact'         => '/views/pages/contact.php',
        'forgot-password' => '/views/auth/forgot_password.php',
        'terms'           => '/views/pages/terms.php',
        'privacy'         => '/views/pages/privacy.php',
        'home'            => '/views/home/index.php',
        'profile'         => '/views/profile/index.php',
        'literature'      => '/views/literature/index.php',
        'lists'           => '/views/lists/index.php',
        'collections'     => '/views/collections/index.php',
    ];

    public function index(): void
    {
        header('Content-Type: application/xml; charset=utf-8');

        $baseUrl = rtrim(APP_URL, '/');

        $xml  = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
        $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"';
        if (ENABLE_HREFLANG) {
            $xml .= ' xmlns:xhtml="http://www.w3.org/1999/xhtml"';
        }
        $xml .= '>' . PHP_EOL;

        // Articles list page — individual articles live in the dedicated articles sitemap.
        try {
            $articlesLastMod = (new Article())->lastModifiedAll();
        } catch (Throwable $e) {
            $articlesLastMod = null;
        }
        $xml .= $this->generateUrlNode($baseUrl . '/articles', '0.9', $articlesLastMod ? date('Y-m-d', strtotime($articlesLastMod)) : null);

        // Marketplace landing — individual listings live in the dedicated marketplace sitemap.
        try {
            require_once APP_ROOT . '/models/Listing.php';
            $marketplaceLastMod = (new Listing())->lastModified();
        } catch (Throwable $e) {
            $marketplaceLastMod = null;
        }
        $xml .= $this->generateUrlNode($baseUrl . '/marketplace', '0.9', $marketplaceLastMod ? date('Y-m-d', strtotime($marketplaceLastMod)) : null);

        $staticPages = [
            ''                => '1.0',
            'support'         => '0.8',
            'contact'         => '0.8',
            'terms'           => '0.5',
            'privacy'         => '0.5',
        ];

        foreach ($staticPages as $path => $priority) {
            $url = $path ? $baseUrl . '/' . $path : $baseUrl;
            $lastmod = $this->staticPageLastMod($path);
            $xml .= ENABLE_HREFLANG
                ? $this->generateMultilingualUrlNode($url, $path, $priority, Lang::supportedLocales(), $lastmod)
                : $this->generateUrlNode($url, $priority, $lastmod);
        }

        $xml .= '</urlset>';

        echo $xml;
        exit;
    }

    /**
     * Sitemap index linking the main sitemap and the articles sitemap.
     */
    public function sitemapIndex(): void
    {
        header('Content-Type: application/xml; charset=utf-8');

        $baseUrl = rtrim(APP_URL, '/');

        // Main sitemap lastmod = newest mtime among static page view files
        $mainLastMod = 0;
        foreach (self::STATIC_PAGE_VIEWS as $relPath) {
            $abs = APP_ROOT . $relPath;
            if (is_file($abs)) {
                $mainLastMod = max($mainLastMod, filemtime($abs));
            }
        }
        $mainLastMod = $mainLastMod > 0 ? date('Y-m-d', $mainLastMod) : null;

        // Articles sitemap lastmod = MAX(updated_at) of published articles
        try {
            $articlesLastModRaw = (new Article())->lastModifiedAll();
        } catch (Throwable $e) {
            $articlesLastModRaw = null;
        }
        $articlesLastMod = $articlesLastModRaw ? date('Y-m-d', strtotime($articlesLastModRaw)) : null;

        $xml  = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
        $xml .= '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . PHP_EOL;

        $xml .= '  <sitemap>' . PHP_EOL;
        $xml .= '    <loc>' . htmlspecialchars($baseUrl . '/sitemap.xml') . '</loc>' . PHP_EOL;
        if ($mainLastMod) {
            $xml .= '    <lastmod>' . $mainLastMod . '</lastmod>' . PHP_EOL;
        }
        $xml .= '  </sitemap>' . PHP_EOL;

        $xml .= '  <sitemap>' . PHP_EOL;
        $xml .= '    <loc>' . htmlspecialchars($baseUrl . '/articles/sitemap.xml') . '</loc>' . PHP_EOL;
        if ($articlesLastMod) {
            $xml .= '    <lastmod>' . $articlesLastMod . '</lastmod>' . PHP_EOL;
        }
        $xml .= '  </sitemap>' . PHP_EOL;

        // Marketplace sitemap
        try {
            require_once APP_ROOT . '/models/Listing.php';
            $marketplaceLastModRaw = (new Listing())->lastModified();
        } catch (Throwable $e) {
            $marketplaceLastModRaw = null;
        }
        $marketplaceLastMod = $marketplaceLastModRaw ? date('Y-m-d', strtotime($marketplaceLastModRaw)) : null;
        $xml .= '  <sitemap>' . PHP_EOL;
        $xml .= '    <loc>' . htmlspecialchars($baseUrl . '/marketplace/sitemap.xml') . '</loc>' . PHP_EOL;
        if ($marketplaceLastMod) {
            $xml .= '    <lastmod>' . $marketplaceLastMod . '</lastmod>' . PHP_EOL;
        }
        $xml .= '  </sitemap>' . PHP_EOL;

        $xml .= '</sitemapindex>';

        echo $xml;
        exit;
    }

    /**
     * Marketplace listings sitemap (one entry per active listing).
     */
    public function marketplace(): void
    {
        header('Content-Type: application/xml; charset=utf-8');

        $baseUrl = rtrim(APP_URL, '/');

        require_once APP_ROOT . '/models/Listing.php';
        try {
            $slugs = (new Listing())->getAllActiveSlugs();
        } catch (Throwable $e) {
            $slugs = [];
        }

        $xml  = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
        $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . PHP_EOL;

        foreach ($slugs as $row) {
            $url = $baseUrl . '/marketplace/' . $row['slug'];
            $lastmod = !empty($row['updated_at']) ? date('Y-m-d', strtotime($row['updated_at'])) : null;
            $xml .= $this->generateUrlNode($url, '0.7', $lastmod);
        }

        $xml .= '</urlset>';

        echo $xml;
        exit;
    }

    private function staticPageLastMod(string $path): ?string
    {
        if (!array_key_exists($path, self::STATIC_PAGE_VIEWS)) {
            return null;
        }
        $abs = APP_ROOT . self::STATIC_PAGE_VIEWS[$path];
        if (!is_file($abs)) {
            return null;
        }
        return date('Y-m-d', filemtime($abs));
    }

    private function generateMultilingualUrlNode(string $url, string $path, string $priority, array $languages, ?string $lastmod = null): string
    {
        $changefreq = $priority >= '0.9' ? 'daily' : ($priority >= '0.7' ? 'weekly' : 'monthly');
        $baseUrl = rtrim(APP_URL, '/');

        $node  = "  <url>" . PHP_EOL;
        $node .= "    <loc>" . htmlspecialchars($url) . "</loc>" . PHP_EOL;
        if ($lastmod) {
            $node .= "    <lastmod>{$lastmod}</lastmod>" . PHP_EOL;
        }
        $node .= "    <changefreq>{$changefreq}</changefreq>" . PHP_EOL;
        $node .= "    <priority>{$priority}</priority>" . PHP_EOL;

        foreach ($languages as $lang) {
            if ($lang === 'en') {
                $langUrl = $url;
            } else {
                $langUrl = $baseUrl . '/lang/' . $lang . ($path ? '/' . $path : '');
            }
            if (!str_starts_with($langUrl, 'http')) {
                $langUrl = $baseUrl . '/' . ltrim($langUrl, '/');
            }
            $hreflang = Lang::hreflangCode($lang);
            $node .= "    <xhtml:link rel=\"alternate\" hreflang=\"{$hreflang}\" href=\"" . htmlspecialchars($langUrl) . "\" />" . PHP_EOL;
        }

        $node .= "    <xhtml:link rel=\"alternate\" hreflang=\"x-default\" href=\"" . htmlspecialchars($url) . "\" />" . PHP_EOL;
        $node .= "  </url>" . PHP_EOL;

        return $node;
    }

    private function generateUrlNode(string $url, string $priority, ?string $lastmod = null): string
    {
        $changefreq = $priority >= '0.9' ? 'daily' : ($priority >= '0.7' ? 'weekly' : 'monthly');

        $node  = "  <url>" . PHP_EOL;
        $node .= "    <loc>" . htmlspecialchars($url) . "</loc>" . PHP_EOL;
        if ($lastmod) {
            $node .= "    <lastmod>{$lastmod}</lastmod>" . PHP_EOL;
        }
        $node .= "    <changefreq>{$changefreq}</changefreq>" . PHP_EOL;
        $node .= "    <priority>{$priority}</priority>" . PHP_EOL;
        $node .= "  </url>" . PHP_EOL;

        return $node;
    }
}
