<?php
/**
 * Petition Map Plugin (page plugin)
 *
 * Enable via metadata.ini:   plugins = "petition-form, petition-map"
 * Requires petition_id to be set (inherited from petition-form setup).
 *
 * Injects template variable $petition_map containing the full widget HTML.
 * Embed in a content file:   <?= $petition_map ?>
 *
 * Data flow:
 *   CSV -> petitionMapBuildData() -> cache (custom/data/) + public JSON (custom/assets/)
 *   Public JSON is served at /petition-map-data.json by the router's asset mechanism.
 *   JS fetches it and renders dots on a Leaflet map.
 *
 * Public JSON format:
 * { "generated": int, "total": int, "regions": { "oslo": { "count": 42, "signers": [{"n":"Kari","a":false}] } } }
 *   n = first name (null for anonymous), a = anonymous (bool)
 *   No emails, surnames, tokens, or IP hashes ever leave the server.
 */

define('PETITION_MAP_CACHE_TTL', 60);
define('PETITION_MAP_CACHE_PATH', dirname(__DIR__, 2) . '/data/petition-map-cache.json');
define('PETITION_MAP_PUBLIC_PATH', dirname(__DIR__, 2) . '/assets/petition-map-data.json');

/**
 * Build public-safe map data from the petition CSV.
 */
function petitionMapBuildData(string $csvPath): array {
    $regions = [];
    $total = 0;

    if (!file_exists($csvPath)) {
        return ['generated' => time(), 'total' => 0, 'regions' => (object)[]];
    }

    $fp = fopen($csvPath, 'r');
    if (!$fp) {
        return ['generated' => time(), 'total' => 0, 'regions' => (object)[]];
    }

    if (flock($fp, LOCK_SH)) {
        fgetcsv($fp, null, ',', '"', '');

        while (($row = fgetcsv($fp, null, ',', '"', '')) !== false) {
            if (!isset($row[6]) || $row[6] !== 'confirmed') continue;

            $region  = $row[4] ?? '';
            $display = $row[5] ?? 'semi';
            if (empty($region)) continue;

            $anonymous = ($display === 'anonymous');
            $name = $anonymous ? null : trim($row[2] ?? '');
            if ($name !== null) {
                // First name only — take the first word to keep map labels compact
                $name = mb_substr(explode(' ', $name)[0], 0, 50);
                if ($name === '') $name = null;
            }

            if (!isset($regions[$region])) {
                $regions[$region] = ['count' => 0, 'signers' => []];
            }

            $regions[$region]['count']++;
            $regions[$region]['signers'][] = ['n' => $name, 'a' => $anonymous];
            $total++;
        }

        flock($fp, LOCK_UN);
    }
    fclose($fp);

    return [
        'generated' => time(),
        'total'     => $total,
        'regions'   => empty($regions) ? (object)[] : $regions,
    ];
}

function petitionMapReadCache(): ?array {
    $path = PETITION_MAP_CACHE_PATH;
    if (!file_exists($path)) return null;
    if ((time() - filemtime($path)) > PETITION_MAP_CACHE_TTL) return null;

    $json = file_get_contents($path);
    if (!$json) return null;

    $data = json_decode($json, true);
    return is_array($data) ? $data : null;
}

function petitionMapWriteCache(array $data): void {
    $json = json_encode($data, JSON_UNESCAPED_UNICODE);
    if ($json === false) return;

    foreach ([PETITION_MAP_CACHE_PATH, PETITION_MAP_PUBLIC_PATH] as $path) {
        $dir = dirname($path);
        if (!is_dir($dir)) {
            mkdir($dir, 0750, true);
        }
        $tmp = $path . '.tmp.' . getmypid();
        if (file_put_contents($tmp, $json, LOCK_EX) !== false) {
            rename($tmp, $path);
        }
    }
}

function petitionMapGetData(string $csvPath): array {
    $cached = petitionMapReadCache();
    if ($cached !== null) return $cached;

    $data = petitionMapBuildData($csvPath);
    petitionMapWriteCache($data);
    return $data;
}

/**
 * Render the map widget HTML block.
 */
function petitionMapRenderWidget(Context $ctx, bool $fullpage = false): string {
    $langPrefix = $ctx->get('langPrefix', '');

    // CSS hash for cache busting
    $cssPath = dirname(__DIR__, 2) . '/assets/petition-map.css';
    $cssHash = file_exists($cssPath) ? substr(hash_file('md5', $cssPath), 0, 8) : '';

    $jsPath = dirname(__DIR__, 2) . '/assets/petition-map.js';
    $jsHash = file_exists($jsPath) ? substr(hash_file('md5', $jsPath), 0, 8) : '';

    $dataJsonPath = PETITION_MAP_PUBLIC_PATH;
    $dataHash = file_exists($dataJsonPath) ? substr(hash_file('md5', $dataJsonPath), 0, 8) : '';

    $html = '';

    // Leaflet CSS
    $html .= '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="anonymous">';

    // Map CSS
    $html .= '<link rel="stylesheet" href="/petition-map.css?v=' . $cssHash . '">';

    // Map container
    $sectionClass = 'petition-map-section escape' . ($fullpage ? ' petition-map-section--fullpage' : '');
    $html .= '<section class="' . $sectionClass . '">';
    $html .= '<h1 id="petition-map-count" class="petition-map-count" aria-live="polite"></h1>';
    $html .= '<div id="petition-map" aria-label="Kart over underskrifter i Norge">';
    $html .= '<div class="map-loading" id="map-loading" aria-live="polite">Laster kart…</div>';
    $iconExpand = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="10 2 14 2 14 6"/><polyline points="6 14 2 14 2 10"/><line x1="14" y1="2" x2="9" y2="7"/><line x1="2" y1="14" x2="7" y2="9"/></svg>';
    if (!$fullpage) {
        $html .= '<a href="' . $langPrefix . '/underskriftskampanje/medisinsk-cannabis-pa-resept/kart/" class="petition-map-fullscreen-btn" title="Fullskjerm" aria-label="Åpne kart i fullskjerm">' . $iconExpand . '</a>';
    }
    if ($fullpage) {
        $iconCollapse = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="10" y1="14" x2="3" y2="21"/><line x1="21" y1="3" x2="14" y2="10"/></svg>';
        $html .= '<a href="' . $langPrefix . '/underskriftskampanje/medisinsk-cannabis-pa-resept/#petition-map" class="petition-map-fullscreen-btn petition-map-fullscreen-btn--minimize" title="Minimer" aria-label="Gå tilbake til underskriftssiden">' . $iconCollapse . '</a>';
    }
    $html .= '</div>';
    $html .= '<a href="' . $langPrefix . '/underskriftskampanje/medisinsk-cannabis-pa-resept/#sign-now" class="petition-map-cta-btn">Signer nå!</a>';
    $html .= '</section>';

    // Config for JS
    $html .= '<script>';
    $html .= 'window.PETITION_MAP_CONFIG={';
    $html .= 'dataUrl:"/petition-map-data.json?v=' . $dataHash . '",';
    $html .= 'geojsonUrl:"/norway-fylker.geojson",';
    $html .= 'anonIconUrl:"/anon.svg",';
    $html .= 'pollInterval:60000';
    $html .= '};';
    $html .= '</script>';

    // Leaflet JS + map JS
    $html .= '<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin="anonymous"></script>';
    $html .= '<script src="/petition-map.js?v=' . $jsHash . '"></script>';

    return $html;
}

// --- Hook ---

Hooks::add(Hook::TEMPLATE_VARS, function(array $vars, Context $ctx) {
    // Resolve page directory and metadata (reuse petition-form helpers if available)
    if (!function_exists('petitionResolvePageDir')) return $vars;
    $pageDir = petitionResolvePageDir($ctx);
    if (!$pageDir) return $vars;

    $metadata = loadMetadata($pageDir);
    $plugins = $metadata['plugins'] ?? '';
    if (strpos($plugins, 'petition-map') === false) return $vars;

    $petitionId = $metadata['petition_id']
        ?? (function_exists('petitionGetIdFromPath') ? petitionGetIdFromPath($pageDir) : null);
    if (!$petitionId) return $vars;

    $petitionId = preg_replace('/[^a-z0-9\-_]/i', '', $petitionId);
    if (empty($petitionId)) return $vars;

    $csvPath = dirname(__DIR__, 2) . "/data/petitions/{$petitionId}.csv";

    // Refresh cache + public JSON if stale
    petitionMapGetData($csvPath);

    // Inject widget HTML as template variable
    $fullpage = !empty($metadata['map_fullpage']);
    $vars['petition_map'] = petitionMapRenderWidget($ctx, $fullpage);

    return $vars;
});
