<?php

declare(strict_types=1);

namespace PrettyLinks\Pro\RedirectTypes;

use PrettyLinks\Repositories\LinkMetas;

/**
 * JavaScript redirect. Emits a minimal HTML page that uses a deferred
 * `window.location` assignment to navigate the browser. Drop-in port of
 * v3's `javascript` redirect type — supports the same per-link `delay`
 * meta (seconds). Target URL is JSON-escaped to avoid breaking the
 * script payload.
 */
final class JavascriptRenderer
{
    /**
     * Link meta repository.
     *
     * @var LinkMetas
     */
    private LinkMetas $linkMetas;

    /**
     * Stores the link meta repository dependency.
     *
     * @param LinkMetas $linkMetas Link meta repository.
     */
    public function __construct(LinkMetas $linkMetas)
    {
        $this->linkMetas = $linkMetas;
    }

    /**
     * `prli_handle_redirect_type` filter callback.
     *
     * @param boolean              $handled Whether the redirect was already handled.
     * @param array<string, mixed> $link    Link row.
     * @param string               $target  Resolved outbound URL.
     * @param integer              $status  HTTP status code.
     * @param string               $type    The link redirect_type value.
     *
     * @return boolean Whether the redirect was handled.
     */
    public function filter(bool $handled, array $link, string $target, int $status, string $type): bool
    {
        unset($status);
        if ($handled || $type !== 'javascript') {
            return $handled;
        }

        $delayMs = $this->delay((int) ($link['id'] ?? 0)) * 1000;
        $title   = (string) ($link['name'] ?? get_bloginfo('name'));

        nocache_headers();
        if (!headers_sent()) {
            header('Content-Type: text/html; charset=utf-8');
            header('X-Pretty-Link: javascript');
        }

        $json = (string) wp_json_encode([
            'url'   => esc_url_raw($target),
            'delay' => $delayMs,
        ]);

        echo '<!doctype html><html lang="en"><head>';
        echo '<meta charset="utf-8">';
        echo '<meta name="robots" content="noindex,nofollow">';
        echo '<title>' . esc_html($title) . '</title>';
        do_action('prli_javascript_redirect_head', $link);
        echo '</head><body>';
        // Script stays inline: the entire page's purpose is to run it,
        // pulling in a static JS file would add a needless round-trip.
        echo '<script>';
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $json is a wp_json_encode() result with esc_url_raw target; safe in a <script> context.
        echo '(function(d){var r=' . $json . ';';
        echo 'var go=function(){window.location.replace(r.url);};';
        echo 'if(r.delay>0){setTimeout(go,r.delay);}else{go();}';
        echo '})(document);';
        echo '</script>';
        echo '</body></html>';
        exit;
    }

    /**
     * Resolves the configured redirect delay for a link, in seconds.
     *
     * @param integer $linkId The link ID.
     *
     * @return integer The delay in seconds.
     */
    private function delay(int $linkId): int
    {
        if ($linkId <= 0) {
            return 0;
        }
        $raw = $this->linkMetas->get($linkId, 'delay', '0');
        return max(0, (int) $raw);
    }
}
