<?php
/**
 * WHP time helpers.
 *
 * Server-side rendering pairs with web-files/js/whp-times.js: each helper
 * emits markup carrying the original UTC value as data-* attributes so the
 * browser can rewrite the visible text/title into the user's locale and
 * timezone. Without JS, the user still sees a sensible UTC fallback.
 *
 * The PHP date() / strftime format string is mapped to a coarse format
 * hint ("date", "datetime", "datetime-seconds") and forwarded to the JS
 * helper via data-format / data-format-title.
 */

if (!function_exists('whp_local_time_normalize')) {
    /**
     * Coerce an int|string|DateTimeInterface input into a Unix timestamp.
     * Returns null when the value can't be parsed — callers should render
     * a static fallback rather than emitting broken markup.
     */
    function whp_local_time_normalize($value): ?int {
        if ($value === null || $value === '' || $value === false) {
            return null;
        }
        if ($value instanceof DateTimeInterface) {
            return $value->getTimestamp();
        }
        if (is_int($value)) {
            return $value;
        }
        if (is_numeric($value)) {
            return (int) $value;
        }
        if (is_string($value)) {
            $ts = strtotime($value);
            return $ts === false ? null : $ts;
        }
        return null;
    }
}

if (!function_exists('whp_local_time_format_hint')) {
    /**
     * Map a PHP date() format string to one of the JS helper's coarse
     * categories. The categories drive toLocaleString() options, so the
     * mapping only needs to capture "date vs datetime" and "with seconds
     * or without".
     */
    function whp_local_time_format_hint(string $format): string {
        $hasTime    = preg_match('/[gGhHisaA]/', $format) === 1;
        $hasSeconds = strpos($format, 's') !== false;
        if (!$hasTime) return 'date';
        return $hasSeconds ? 'datetime-seconds' : 'datetime';
    }
}

if (!function_exists('whp_local_time')) {
    /**
     * Render a timestamp as a span the JS helper will rewrite to the
     * browser's locale + timezone.
     *
     * Output shape:
     *   <span class="local-time" data-utc="ISO" data-format="datetime">
     *     UTC fallback formatted by $format
     *   </span>
     *
     * @param mixed  $value  Unix int, MySQL DATETIME string, ISO string, or DateTimeInterface.
     * @param string $format PHP date() format used for the no-JS fallback.
     */
    function whp_local_time($value, string $format = 'M j, Y g:i A'): string {
        $ts = whp_local_time_normalize($value);
        if ($ts === null) {
            return '<span class="text-muted">—</span>';
        }
        $isoUtc   = gmdate('Y-m-d\TH:i:s\Z', $ts);
        // Fallback uses gmdate so what users without JS see matches what
        // the data-utc attribute promises (UTC, not server-local).
        $fallback = gmdate($format, $ts);
        $hint     = whp_local_time_format_hint($format);
        return sprintf(
            '<span class="local-time" data-utc="%s" data-format="%s">%s</span>',
            htmlspecialchars($isoUtc, ENT_QUOTES, 'UTF-8'),
            htmlspecialchars($hint, ENT_QUOTES, 'UTF-8'),
            htmlspecialchars($fallback, ENT_QUOTES, 'UTF-8')
        );
    }
}

if (!function_exists('whp_local_time_title_attrs')) {
    /**
     * Render the data-utc-title and title attributes for a tag whose
     * visible text is something OTHER than the timestamp (e.g., a relative
     * duration like "4d 2h"), but whose tooltip should be the absolute
     * timestamp in the user's local timezone.
     *
     * Drop the return value into the opening tag — already includes the
     * leading space and is htmlspecialchars-safe.
     *
     *   <small <?= whp_local_time_title_attrs($ts) ?>>4d 2h</small>
     */
    function whp_local_time_title_attrs($value, string $format = 'Y-m-d H:i:s'): string {
        $ts = whp_local_time_normalize($value);
        if ($ts === null) return '';
        $isoUtc   = gmdate('Y-m-d\TH:i:s\Z', $ts);
        $fallback = gmdate($format, $ts);
        $hint     = whp_local_time_format_hint($format);
        return sprintf(
            ' data-utc-title="%s" data-format-title="%s" title="%s"',
            htmlspecialchars($isoUtc, ENT_QUOTES, 'UTF-8'),
            htmlspecialchars($hint, ENT_QUOTES, 'UTF-8'),
            htmlspecialchars($fallback, ENT_QUOTES, 'UTF-8')
        );
    }
}
