<?php

require dirname(__DIR__) . '/includes/init.php';

try {
    db()->query('SELECT 1');
} catch (Throwable $e) {
    error_log($e->getMessage());
    http_response_code(500);
    echo '<h1>NeraFlores belum terhubung ke database</h1>';
    echo '<p>Impor database/schema.sql dan database/seed.sql, lalu periksa file .env.</p>';
    if (env('APP_DEBUG') === '1') {
        echo '<pre>' . e($e->getMessage()) . '</pre>';
    }
    exit;
}

$path = request_path();
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

if ($method === 'POST' && $path === 'kontak') {
    handle_contact();
}
if ($method === 'POST' && $path === 'warta') {
    handle_newsletter();
}
if ($path === 'sitemap.xml') {
    render_sitemap();
}
if ($path === 'sitemap-news.xml') {
    render_news_sitemap();
}
if ($path === 'robots.txt') {
    render_robots();
}
if ($path === 'feed.xml') {
    render_feed();
}
if ($path === 'cari' && ($_GET['format'] ?? '') === 'json') {
    render_search_json();
}

$seo = default_seo();

if ($path === '' || $path === 'index.php') {
    $seo = [
        'title' => seo_title(setting('home_seo_title'), setting('site_name') . ' | Berita Flores dan NTT'),
        'description' => seo_title(setting('home_seo_description'), setting('site_description')),
        'canonical' => url(''),
        'robots' => setting('home_robots_index', '1') === '1' ? 'index, follow' : 'noindex, follow',
        'image' => absolute_url(media(setting('home_og_image', 'assets/images/logo-nf.png'))),
        'jsonld' => [
            '@context' => 'https://schema.org',
            '@graph' => [
                organization_schema(),
                [
                    '@type' => 'WebSite',
                    '@id' => url('') . '#website',
                    'url' => url(''),
                    'name' => setting('site_name'),
                    'inLanguage' => 'id-ID',
                    'publisher' => ['@id' => url('') . '#organization'],
                ],
            ],
        ],
    ];
    view('home');
}

if (preg_match('#^berita/([a-z0-9-]+)$#', $path, $m)) {
    $article = find_article($m[1]);
    if (!$article || (int) $article['robots_index'] !== 1 && false) {
        render_404();
    }
    if (!$article) {
        render_404();
    }
    $title = seo_title($article['seo_title'], $article['title'] . ' | ' . setting('site_name'));
    $description = seo_title($article['seo_description'], (string) $article['excerpt']);
    $image = absolute_url(media($article['og_image'] ?: $article['image'] ?: setting('logo_path')));
    $seo = [
        'title' => $title,
        'description' => $description,
        'og_title' => seo_title($article['og_title'], $title),
        'og_description' => seo_title($article['og_description'], $description),
        'canonical' => url('berita/' . $article['slug']),
        'robots' => (int) $article['robots_index'] === 1 ? 'index, follow' : 'noindex, follow',
        'type' => 'article',
        'image' => $image,
        'jsonld' => [
            '@context' => 'https://schema.org',
            '@graph' => [
                [
                    '@type' => 'NewsArticle',
                    'headline' => $article['title'],
                    'description' => $description,
                    'datePublished' => date('c', strtotime($article['published_at'] ?: $article['created_at'])),
                    'dateModified' => date('c', strtotime($article['updated_at'])),
                    'inLanguage' => 'id-ID',
                    'image' => [$image],
                    'author' => ['@type' => 'Person', 'name' => $article['author']],
                    'publisher' => organization_schema(),
                    'mainEntityOfPage' => url('berita/' . $article['slug']),
                    'isAccessibleForFree' => true,
                ],
                breadcrumb_schema([
                    ['Beranda', url('')],
                    [$article['category_name'] ?: 'Berita', $article['category_slug'] ? url('kategori/' . $article['category_slug']) : url('arsip')],
                    [$article['title'], url('berita/' . $article['slug'])],
                ]),
            ],
        ],
    ];
    view('article');
}

if (preg_match('#^kategori/([a-z0-9-]+)(?:/halaman/([0-9]+))?$#', $path, $m)) {
    if ($m[1] === 'foto') {
        redirect('/foto');
    }
    if ($m[1] === 'video') {
        redirect('/video');
    }
    $category = find_category($m[1]);
    if (!$category) {
        render_404();
    }
    $pageNo = isset($m[2]) ? (int) $m[2] : 1;
    render_listing(
        'c.slug = ?',
        [$category['slug']],
        '/kategori/' . $category['slug'],
        $category['name'],
        'Rubrik',
        (string) $category['description'],
        $pageNo,
        $category
    );
}

if (preg_match('#^wilayah/([a-z0-9-]+)(?:/halaman/([0-9]+))?$#', $path, $m)) {
    $region = find_region($m[1]);
    if (!$region) {
        render_404();
    }
    $pageNo = isset($m[2]) ? (int) $m[2] : 1;
    $cover = $region['image'];
    render_listing(
        'r.slug = ?',
        [$region['slug']],
        '/wilayah/' . $region['slug'],
        $region['name'],
        $region['group_name'] === 'ntt' ? 'NTT' : 'Flores',
        trim(($region['tagline'] ? $region['tagline'] . ' ' : '') . (string) $region['description']),
        $pageNo,
        $region,
        $cover
    );
}

if (preg_match('#^tag/([a-z0-9-]+)(?:/halaman/([0-9]+))?$#', $path, $m)) {
    $tag = find_tag($m[1]);
    if (!$tag) {
        render_404();
    }
    $pageNo = isset($m[2]) ? (int) $m[2] : 1;
    render_listing(
        'EXISTS (SELECT 1 FROM article_tags at INNER JOIN tags t ON t.id = at.tag_id WHERE at.article_id = a.id AND t.slug = ?)',
        [$tag['slug']],
        '/tag/' . $tag['slug'],
        '#' . $tag['name'],
        'Tag',
        'Berita bertanda ' . $tag['name'] . '.',
        $pageNo,
        ['seo_title' => $tag['name'] . ' | ' . setting('site_name'), 'seo_description' => 'Berita bertanda ' . $tag['name'], 'robots_index' => 1, 'og_title' => '', 'og_description' => '', 'og_image' => '']
    );
}

if (preg_match('#^arsip(?:/halaman/([0-9]+))?$#', $path, $m)) {
    render_listing('', [], '/arsip', 'Arsip Berita', 'Terkini', 'Seluruh berita yang telah diterbitkan NeraFlores.', isset($m[1]) ? (int) $m[1] : 1, [
        'seo_title' => 'Arsip Berita | ' . setting('site_name'),
        'seo_description' => 'Arsip berita Flores dan Nusa Tenggara Timur.',
        'robots_index' => 1,
    ]);
}

if (preg_match('#^foto(?:/halaman/([0-9]+))?$#', $path, $m)) {
    render_listing("a.media_type = 'photo' OR c.slug = 'foto'", [], '/foto', 'Foto', 'Visual', 'Berita berbasis foto dari Flores dan NTT.', isset($m[1]) ? (int) $m[1] : 1, [
        'seo_title' => 'Foto | ' . setting('site_name'),
        'seo_description' => 'Galeri berita foto NeraFlores.',
        'robots_index' => 1,
    ]);
}

if (preg_match('#^video(?:/halaman/([0-9]+))?$#', $path, $m)) {
    render_listing("a.media_type = 'video' OR c.slug = 'video'", [], '/video', 'Video', 'Visual', 'Berita video NeraFlores.', isset($m[1]) ? (int) $m[1] : 1, [
        'seo_title' => 'Video | ' . setting('site_name'),
        'seo_description' => 'Berita video NeraFlores.',
        'robots_index' => 1,
    ]);
}

if ($path === 'cari') {
    $query = trim((string) ($_GET['q'] ?? ''));
    $articles = [];
    if ($query !== '') {
        $like = '%' . $query . '%';
        $articles = fetch_articles('a.title LIKE ? OR a.excerpt LIKE ? OR a.body LIKE ? OR c.name LIKE ? OR r.name LIKE ?', [$like, $like, $like, $like, $like], 'a.published_at DESC', 30);
    }
    $seo = [
        'title' => 'Pencarian | ' . setting('site_name'),
        'description' => 'Cari berita NeraFlores.',
        'canonical' => url('cari'),
        'robots' => 'noindex, follow',
    ];
    view('search');
}

if ($path === 'kontak') {
    $page = find_page('kontak') ?: ['title' => 'Hubungi Redaksi', 'seo_title' => '', 'seo_description' => 'Kirim informasi ke redaksi NeraFlores.', 'robots_index' => 1];
    $seo = page_seo($page, '/kontak');
    $errors = $_SESSION['contact_errors'] ?? [];
    $old = $_SESSION['contact_old'] ?? [];
    unset($_SESSION['contact_errors'], $_SESSION['contact_old']);
    view('contact');
}

if ($path === 'tentang') {
    $page = find_page('tentang');
    if (!$page) {
        render_404();
    }
    $seo = page_seo($page, '/tentang');
    view('page');
}

if (preg_match('#^[a-z0-9-]+$#', $path)) {
    $reserved = ['admin', 'assets', 'uploads', 'berita', 'kategori', 'wilayah', 'tag', 'foto', 'video', 'arsip', 'cari', 'kontak', 'tentang'];
    if (!in_array($path, $reserved, true)) {
        $page = find_page($path);
        if ($page) {
            $seo = page_seo($page, '/' . $page['slug']);
            view('page');
        }
    }
}

render_404();

function default_seo(): array
{
    return [
        'title' => setting('site_name'),
        'description' => setting('site_description'),
        'canonical' => url(request_path()),
        'robots' => 'index, follow',
        'type' => 'website',
        'image' => absolute_url(media(setting('logo_path', 'assets/images/logo-nf.png'))),
    ];
}

function page_seo(array $page, string $path): array
{
    $title = seo_title($page['seo_title'] ?? '', ($page['title'] ?? 'Halaman') . ' | ' . setting('site_name'));
    $description = seo_title($page['seo_description'] ?? '', (string) ($page['excerpt'] ?? setting('site_description')));
    return [
        'title' => $title,
        'description' => $description,
        'og_title' => seo_title($page['og_title'] ?? '', $title),
        'og_description' => seo_title($page['og_description'] ?? '', $description),
        'canonical' => url(ltrim($path, '/')),
        'robots' => (int) ($page['robots_index'] ?? 1) === 1 ? 'index, follow' : 'noindex, follow',
        'image' => absolute_url(media($page['og_image'] ?? setting('logo_path', 'assets/images/logo-nf.png'))),
        'jsonld' => [
            '@context' => 'https://schema.org',
            '@graph' => [
                breadcrumb_schema([
                    ['Beranda', url('')],
                    [$page['title'] ?? 'Halaman', url(ltrim($path, '/'))],
                ]),
            ],
        ],
    ];
}

function breadcrumb_schema(array $items): array
{
    $list = [];
    foreach ($items as $i => $item) {
        $list[] = [
            '@type' => 'ListItem',
            'position' => $i + 1,
            'name' => $item[0],
            'item' => $item[1],
        ];
    }
    return ['@type' => 'BreadcrumbList', 'itemListElement' => $list];
}

function view(string $name): never
{
    global $seo, $article, $articles, $query, $errors, $old, $page, $heading, $kicker, $intro, $pager, $pageBase, $cover;
    include dirname(__DIR__) . '/includes/header.php';
    include dirname(__DIR__) . '/pages/' . $name . '.php';
    include dirname(__DIR__) . '/includes/footer.php';
    exit;
}

function render_404(): never
{
    global $seo;
    http_response_code(404);
    $seo = [
        'title' => 'Halaman tidak ditemukan | ' . setting('site_name'),
        'description' => 'Halaman yang Anda cari tidak tersedia.',
        'canonical' => url(request_path()),
        'robots' => 'noindex, follow',
    ];
    view('404');
}

function render_listing(string $where, array $params, string $base, string $heading, string $kicker, string $intro, int $pageNo, array $meta, ?string $cover = null): never
{
    $headingValue = $heading;
    $kickerValue = $kicker;
    $introValue = $intro;
    $coverValue = $cover;
    global $seo, $articles, $pager, $pageBase, $heading, $kicker, $intro, $cover;
    $pageBase = $base;
    $heading = $headingValue;
    $kicker = $kickerValue;
    $intro = $introValue;
    $cover = $coverValue;
    $total = count_articles($where, $params);
    $pager = pagination($total, $pageNo, 9);
    if ($pageNo > $pager['pages'] && $total > 0) {
        render_404();
    }
    $articles = fetch_articles($where, $params, 'a.published_at DESC', $pager['per_page'], $pager['offset']);
    $title = seo_title($meta['seo_title'] ?? '', $heading . ' | ' . setting('site_name'));
    $description = seo_title($meta['seo_description'] ?? '', $intro);
    $seo = [
        'title' => $title,
        'description' => $description,
        'og_title' => seo_title($meta['og_title'] ?? '', $title),
        'og_description' => seo_title($meta['og_description'] ?? '', $description),
        'canonical' => url(ltrim(page_url($base, $pager['page']), '/')),
        'robots' => (int) ($meta['robots_index'] ?? 1) === 1 ? 'index, follow' : 'noindex, follow',
        'image' => absolute_url(media($meta['og_image'] ?? ($cover ?: setting('logo_path', 'assets/images/logo-nf.png')))),
        'jsonld' => [
            '@context' => 'https://schema.org',
            '@graph' => [breadcrumb_schema([['Beranda', url('')], [$heading, url(ltrim($base, '/'))]])],
        ],
    ];
    $kicker = $kicker;
    $intro = $intro;
    view('listing');
}

function handle_contact(): never
{
    if (!csrf_verify() || !empty($_POST['company_website'])) {
        $_SESSION['contact_errors'] = ['Permintaan tidak dapat diproses. Muat ulang halaman lalu coba lagi.'];
        redirect('/kontak');
    }
    $old = [
        'nama' => trim((string) ($_POST['nama'] ?? '')),
        'nomor_wa' => trim((string) ($_POST['nomor_wa'] ?? '')),
        'jenis' => trim((string) ($_POST['jenis'] ?? '')),
        'lokasi' => trim((string) ($_POST['lokasi'] ?? '')),
        'judul' => trim((string) ($_POST['judul'] ?? '')),
        'pesan' => trim((string) ($_POST['pesan'] ?? '')),
    ];
    $errors = [];
    if ($old['nama'] === '' || mb_strlen($old['nama']) > 160) {
        $errors[] = 'Nama lengkap wajib diisi.';
    }
    if (!preg_match('/^[0-9+\s()-]{8,20}$/', $old['nomor_wa'])) {
        $errors[] = 'Nomor WhatsApp tidak valid.';
    }
    $allowedTypes = ['Informasi Berita', 'Koreksi atau Klarifikasi', 'Kerja Sama', 'Pertanyaan Umum', 'Lainnya'];
    if (!in_array($old['jenis'], $allowedTypes, true)) {
        $errors[] = 'Jenis pesan tidak valid.';
    }
    if ($old['judul'] === '' || mb_strlen($old['judul']) > 255) {
        $errors[] = 'Judul informasi wajib diisi.';
    }
    if ($old['pesan'] === '' || mb_strlen($old['pesan']) > 5000) {
        $errors[] = 'Pesan wajib diisi dan tidak lebih dari 5000 karakter.';
    }
    if ($errors) {
        $_SESSION['contact_errors'] = $errors;
        $_SESSION['contact_old'] = $old;
        redirect('/kontak');
    }
    $dup = db()->prepare('SELECT id FROM contact_messages WHERE whatsapp = ? AND subject = ? AND created_at > ? LIMIT 1');
    $dup->execute([$old['nomor_wa'], $old['judul'], date('Y-m-d H:i:s', time() - 120)]);
    if ($dup->fetch()) {
        flash('Pesan yang sama baru saja terkirim. Redaksi akan meninjaunya.');
        redirect('/kontak');
    }
    $stmt = db()->prepare('INSERT INTO contact_messages (name, whatsapp, message_type, location, subject, message, is_read, created_at) VALUES (?, ?, ?, ?, ?, ?, 0, ?)');
    $stmt->execute([$old['nama'], $old['nomor_wa'], $old['jenis'], $old['lokasi'], $old['judul'], $old['pesan'], now()]);
    flash('Pesan Anda sudah diterima redaksi. Terima kasih.');
    redirect('/kontak');
}

function handle_newsletter(): never
{
    if (!csrf_verify() || !empty($_POST['company_website'])) {
        redirect('/');
    }
    $email = trim((string) ($_POST['email'] ?? ''));
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $_SESSION['newsletter_error'] = 'Alamat email tidak valid.';
        redirect('/#berita-terbaru');
    }
    $stmt = db()->prepare('INSERT INTO newsletter_subscribers (email, status, created_at) VALUES (?, \'active\', ?) ON DUPLICATE KEY UPDATE status = \'active\'');
    $stmt->execute([$email, now()]);
    flash('Terima kasih. Anda terdaftar untuk warta NeraFlores.');
    redirect('/#berita-terbaru');
}

function render_search_json(): never
{
    header('Content-Type: application/json; charset=utf-8');
    $query = trim((string) ($_GET['q'] ?? ''));
    $items = [];
    if (mb_strlen($query) >= 2) {
        $like = '%' . $query . '%';
        $rows = fetch_articles('a.title LIKE ? OR a.excerpt LIKE ? OR c.name LIKE ? OR r.name LIKE ?', [$like, $like, $like, $like], 'a.published_at DESC', 8);
        foreach ($rows as $row) {
            $items[] = [
                'title' => $row['title'],
                'url' => '/berita/' . $row['slug'],
                'category' => $row['category_name'],
                'region' => $row['region_name'],
                'excerpt' => $row['excerpt'],
                'reading_time' => $row['reading_time'],
            ];
        }
    }
    echo json_encode(['items' => $items], JSON_UNESCAPED_UNICODE);
    exit;
}

function render_sitemap(): never
{
    header('Content-Type: application/xml; charset=utf-8');
    $urls = [url('')];
    foreach (['arsip', 'foto', 'video', 'tentang', 'kontak', 'redaksi', 'pedoman-media-siber', 'kebijakan-privasi', 'disclaimer'] as $static) {
        $urls[] = url($static);
    }
    $cats = db()->query("SELECT slug FROM categories WHERE status = 'active' AND robots_index = 1 AND slug NOT IN ('foto','video')")->fetchAll();
    foreach ($cats as $cat) {
        $urls[] = url('kategori/' . $cat['slug']);
    }
    $regions = db()->query("SELECT slug FROM regions WHERE status = 'active' AND robots_index = 1")->fetchAll();
    foreach ($regions as $region) {
        $urls[] = url('wilayah/' . $region['slug']);
    }
    $pages = db()->query("SELECT slug FROM pages WHERE status = 'published' AND robots_index = 1")->fetchAll();
    foreach ($pages as $page) {
        if (!in_array($page['slug'], ['tentang', 'kontak', 'redaksi', 'pedoman-media-siber', 'kebijakan-privasi', 'disclaimer'], true)) {
            $urls[] = url($page['slug']);
        }
    }
    $articles = db()->prepare('SELECT slug, updated_at FROM articles WHERE status = \'published\' AND robots_index = 1 AND (published_at IS NULL OR published_at <= ?)');
    $articles->execute([now()]);
    echo '<?xml version="1.0" encoding="UTF-8"?>';
    echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
    foreach (array_unique($urls) as $loc) {
        echo '<url><loc>' . e($loc) . '</loc></url>';
    }
    foreach ($articles as $article) {
        echo '<url><loc>' . e(url('berita/' . $article['slug'])) . '</loc><lastmod>' . e(date('c', strtotime($article['updated_at']))) . '</lastmod></url>';
    }
    echo '</urlset>';
    exit;
}

function render_news_sitemap(): never
{
    header('Content-Type: application/xml; charset=utf-8');
    $stmt = db()->prepare('SELECT a.title, a.slug, a.published_at, c.name AS category_name FROM articles a LEFT JOIN categories c ON c.id = a.category_id WHERE a.status = \'published\' AND a.robots_index = 1 AND a.published_at >= ?');
    $stmt->execute([date('Y-m-d H:i:s', time() - 172800)]);
    echo '<?xml version="1.0" encoding="UTF-8"?>';
    echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">';
    foreach ($stmt as $article) {
        echo '<url><loc>' . e(url('berita/' . $article['slug'])) . '</loc><news:news><news:publication><news:name>' . e(setting('site_name')) . '</news:name><news:language>id</news:language></news:publication><news:publication_date>' . e(date('c', strtotime($article['published_at']))) . '</news:publication_date><news:title>' . e($article['title']) . '</news:title></news:news></url>';
    }
    echo '</urlset>';
    exit;
}

function render_robots(): never
{
    header('Content-Type: text/plain; charset=utf-8');
    echo "User-agent: *\nAllow: /\nDisallow: /admin/\nDisallow: /cari\n\nSitemap: " . url('sitemap.xml') . "\n";
    exit;
}

function render_feed(): never
{
    header('Content-Type: application/rss+xml; charset=utf-8');
    $rows = fetch_articles('', [], 'a.published_at DESC', 20);
    echo '<?xml version="1.0" encoding="UTF-8"?>';
    echo '<rss version="2.0"><channel>';
    echo '<title>' . e(setting('site_name')) . '</title>';
    echo '<link>' . e(url('')) . '</link>';
    echo '<description>' . e(setting('site_description')) . '</description>';
    echo '<language>id</language>';
    foreach ($rows as $row) {
        echo '<item>';
        echo '<title>' . e($row['title']) . '</title>';
        echo '<link>' . e(url('berita/' . $row['slug'])) . '</link>';
        echo '<guid>' . e(url('berita/' . $row['slug'])) . '</guid>';
        echo '<pubDate>' . e(date(DATE_RSS, strtotime($row['published_at'] ?: $row['created_at']))) . '</pubDate>';
        echo '<description>' . e($row['excerpt']) . '</description>';
        echo '</item>';
    }
    echo '</channel></rss>';
    exit;
}
