<?php
/**
 * HTML Renderer helper — the swap point for future UI changes.
 *
 * Today: returns HTML strings (uses WordPress core admin markup).
 * Tomorrow (Y1.5+): can be replaced with React/MUI render() calls
 * without touching any page-level business logic.
 *
 * All admin pages should call these helpers rather than emitting
 * raw HTML strings inline. This is the seam.
 *
 * @package SwapAds\Client\Admin
 * @since   1.0.0
 */

declare(strict_types=1);

namespace SwapAds\Client\Admin;

/**
 * Class Renderer
 *
 * @since 1.0.0
 */
final class Renderer
{
    /**
     * Open a wrap container with h1.
     */
    public static function pageHeader(string $title, string $description = ''): string
    {
        $h = '<div class="wrap swapads-page">';
        $h .= '<h1>' . esc_html($title) . '</h1>';
        if ($description !== '') {
            $h .= '<p class="description">' . esc_html($description) . '</p>';
        }
        return $h;
    }

    /**
     * Close the wrap container.
     */
    public static function pageFooter(): string
    {
        return '</div>';
    }

    /**
     * Card container (styled via the .swapads-card CSS class).
     *
     * @param string $title  h2 heading shown at top of card
     * @param string $body   HTML body content (already escaped by caller)
     */
    public static function card(string $title, string $body, string $extraClass = ''): string
    {
        $cls = 'swapads-card' . ($extraClass !== '' ? ' ' . $extraClass : '');
        $h = '<div class="' . esc_attr($cls) . '">';
        if ($title !== '') {
            $h .= '<h2>' . esc_html($title) . '</h2>';
        }
        $h .= $body;
        $h .= '</div>';
        return $h;
    }

    /**
     * Notice (success/error/warning).
     */
    public static function notice(string $message, string $type = 'success'): string
    {
        $type = in_array($type, ['success', 'error', 'warning', 'info'], true) ? $type : 'info';
        return '<div class="notice notice-' . esc_attr($type) . ' is-dismissible"><p>' . esc_html($message) . '</p></div>';
    }

    /**
     * Label + text input field.
     */
    public static function textField(string $name, string $label, string $value = '', string $placeholder = '', string $helpText = ''): string
    {
        $h = '<tr>';
        $h .= '<th scope="row"><label for="' . esc_attr($name) . '">' . esc_html($label) . '</label></th>';
        $h .= '<td>';
        $h .= '<input type="text" id="' . esc_attr($name) . '" name="' . esc_attr($name) . '" '
            . 'value="' . esc_attr($value) . '" '
            . 'placeholder="' . esc_attr($placeholder) . '" '
            . 'class="regular-text">';
        if ($helpText !== '') {
            $h .= '<p class="description">' . esc_html($helpText) . '</p>';
        }
        $h .= '</td>';
        $h .= '</tr>';
        return $h;
    }

    /**
     * Label + textarea field.
     */
    public static function textareaField(string $name, string $label, string $value = '', int $rows = 4, string $helpText = ''): string
    {
        $h = '<tr>';
        $h .= '<th scope="row"><label for="' . esc_attr($name) . '">' . esc_html($label) . '</label></th>';
        $h .= '<td>';
        $h .= '<textarea id="' . esc_attr($name) . '" name="' . esc_attr($name) . '" rows="' . (int) $rows . '" '
            . 'class="large-text">' . esc_textarea($value) . '</textarea>';
        if ($helpText !== '') {
            $h .= '<p class="description">' . esc_html($helpText) . '</p>';
        }
        $h .= '</td>';
        $h .= '</tr>';
        return $h;
    }

    /**
     * Label + select dropdown.
     *
     * @param array<int, array{value: string, label: string}> $options
     */
    public static function selectField(string $name, string $label, array $options, string $selected = '', string $helpText = ''): string
    {
        $h = '<tr>';
        $h .= '<th scope="row"><label for="' . esc_attr($name) . '">' . esc_html($label) . '</label></th>';
        $h .= '<td>';
        $h .= '<select id="' . esc_attr($name) . '" name="' . esc_attr($name) . '">';
        foreach ($options as $opt) {
            $sel = selected($selected, $opt['value'], false);
            $h .= '<option value="' . esc_attr($opt['value']) . '" ' . $sel . '>' . esc_html($opt['label']) . '</option>';
        }
        $h .= '</select>';
        if ($helpText !== '') {
            $h .= '<p class="description">' . esc_html($helpText) . '</p>';
        }
        $h .= '</td>';
        $h .= '</tr>';
        return $h;
    }

    /**
     * Label + checkbox.
     */
    public static function checkboxField(string $name, string $label, bool $checked = false, string $helpText = ''): string
    {
        $h = '<tr>';
        $h .= '<th scope="row">' . esc_html($label) . '</th>';
        $h .= '<td>';
        $h .= '<label><input type="checkbox" name="' . esc_attr($name) . '" value="1" ' . checked($checked, true, false) . '> ';
        $h .= esc_html($label);
        $h .= '</label>';
        if ($helpText !== '') {
            $h .= '<p class="description">' . esc_html($helpText) . '</p>';
        }
        $h .= '</td>';
        $h .= '</tr>';
        return $h;
    }

    /**
     * Radio group.
     *
     * @param array<int, array{value: string, label: string}> $options
     */
    public static function radioField(string $name, string $label, array $options, string $selected = '', string $helpText = ''): string
    {
        $h = '<tr>';
        $h .= '<th scope="row">' . esc_html($label) . '</th>';
        $h .= '<td><fieldset>';
        foreach ($options as $opt) {
            $h .= '<label style="margin-right:12px;">';
            $h .= '<input type="radio" name="' . esc_attr($name) . '" value="' . esc_attr($opt['value']) . '" '
                . checked($selected, $opt['value'], false) . '> ';
            $h .= esc_html($opt['label']);
            $h .= '</label>';
        }
        $h .= '</fieldset>';
        if ($helpText !== '') {
            $h .= '<p class="description">' . esc_html($helpText) . '</p>';
        }
        $h .= '</td>';
        $h .= '</tr>';
        return $h;
    }

    /**
     * Open a form tag pointing to admin-post.php.
     */
    public static function formOpen(string $action, string $nonceAction, string $submitLabel = 'Submit'): string
    {
        $h = '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '">';
        $h .= wp_nonce_field($nonceAction, '_wpnonce', true, false);
        $h .= '<input type="hidden" name="action" value="' . esc_attr($action) . '">';
        return $h;
    }

    /**
     * Close form + emit submit button.
     */
    public static function formClose(string $submitLabel = 'Save Changes', string $cancelUrl = ''): string
    {
        $h = '</tbody></table>';
        if ($cancelUrl !== '') {
            $h .= '<a href="' . esc_url($cancelUrl) . '" class="button">' . esc_html__('Cancel', 'swapads-client') . '</a> ';
        }
        $h .= '<button type="submit" class="button button-primary">' . esc_html($submitLabel) . '</button>';
        $h .= '</form>';
        return $h;
    }

    /**
     * Open a form-table tbody.
     */
    public static function formTableOpen(): string
    {
        return '<table class="form-table"><tbody>';
    }

    /**
     * Close a form-table tbody.
     */
    public static function formTableClose(): string
    {
        return '</tbody>';
    }

    /**
     * Plain key-value row (read-only display).
     */
    public static function kvRow(string $label, string $value): string
    {
        return '<tr><th scope="row">' . esc_html($label) . '</th><td>' . $value . '</td></tr>';
    }

    /**
     * Accessible notice (Feedback + Accessibility principles).
     *
     * WP core `notice-*` classes are styled by WP admin. Adds `role="alert"` +
     * `aria-live="polite"` so screen readers announce the change without
     * interrupting the user (WCAG 2.1 AA: 4.1.3 Status Messages).
     *
     * Use for success/error/warning/info messages that should be announced.
     *
     * @param string $type 'success' | 'error' | 'warning' | 'info'
     */
    public static function noticeAccessible(string $message, string $type = 'success'): string
    {
        $type = in_array($type, ['success', 'error', 'warning', 'info'], true) ? $type : 'info';
        return '<div class="notice notice-' . esc_attr($type) . ' is-dismissible" '
             . 'role="alert" aria-live="polite">'
             . '<p>' . esc_html($message) . '</p>'
             . '</div>';
    }

    /**
     * Loading skeleton placeholder (Feedback principle).
     *
     * Whenever a page fetches data from the server, render this skeleton
     * first so the user sees visual progress within ~200ms (Performance
     * principle). The skeleton is replaced by real content once the fetch
     * returns. Reduces perceived latency and prevents layout shift.
     *
     * @param string $kind 'tiles' | 'table' | 'paragraph' | 'card'
     * @param int    $rows Number of skeleton rows (default 3).
     */
    public static function renderLoadingSkeleton(string $kind = 'card', int $rows = 3): string
    {
        $h = '<div class="swapads-skeleton swapads-skeleton-' . esc_attr($kind) . '" aria-busy="true" aria-live="polite">';
        for ($i = 0; $i < $rows; $i++) {
            $h .= '<div class="swapads-skeleton-row"></div>';
        }
        $h .= '</div>';
        return $h;
    }

    /**
     * Empty-state block (per UX-SPEC §1.4 + Feedback principle).
     *
     * When a list/query has no rows, show a friendly empty state with a
     * clear next action (CTA). Avoids the "lonely Nothing found" dead-end
     * that operators hit today.
     *
     * @param string      $title    Bold heading (e.g. "No backlinks yet")
     * @param string      $body     Explanatory text below
     * @param string|null $ctaUrl   Optional URL for the primary CTA
     * @param string|null $ctaLabel Optional CTA button label
     */
    public static function renderEmptyState(
        string $title,
        string $body,
        ?string $ctaUrl = null,
        ?string $ctaLabel = null
    ): string {
        $h  = '<div class="swapads-empty-state" role="status">';
        $h .= '<div class="swapads-empty-icon" aria-hidden="true">📅</div>';
        $h .= '<h3 class="swapads-empty-title">' . esc_html($title) . '</h3>';
        $h .= '<p class="swapads-empty-body">' . esc_html($body) . '</p>';
        if ($ctaUrl !== null && $ctaLabel !== null) {
            $h .= '<a href="' . esc_url($ctaUrl) . '" class="button button-primary">'
                . esc_html($ctaLabel) . '</a>';
        }
        $h .= '</div>';
        return $h;
    }

    /**
     * Inline help icon with tooltip (Discovery principle).
     *
     * Renders a small "?" icon that reveals a tooltip on hover/focus. Uses
     * WP's built-in screen-reader-text pattern for SR-only labels.
     *
     * @param string $text Plain-text help shown in the tooltip.
     * @param string $id   Unique DOM id (caller must ensure uniqueness).
     */
    public static function renderHelpIcon(string $text, string $id): string
    {
        return '<span class="swapads-help-icon" role="tooltip" id="' . esc_attr($id) . '">'
             . '?<span class="screen-reader-text">' . esc_html($text) . '</span>'
             . '</span>';
    }

    /**
     * Render the shared page footer (Consistency principle).
     *
     * Every page SHOULD call this in lieu of `Renderer::pageFooter()` so the
     * Help / Docs link is consistent across the plugin. Future global
     * footer chrome (version, build SHA, support links) lands here.
     *
     * @param string $extra HTML to inject before the closing wrap div (rare).
     */
    public static function pageFooterWithHelpers(string $extra = ''): string
    {
        $h  = $extra;
        $h .= '<div class="swapads-page-footer" role="contentinfo">';
        $h .= '<p class="swapads-page-footer-meta">';
        $h .= '<a href="https://swapads.eu/docs/operator" target="_blank" rel="noopener">'
             . esc_html__('Help & Docs', 'swapads-client') . '</a>';
        $h .= ' Â· ';
        $h .= '<a href="https://swapads.eu/support" target="_blank" rel="noopener">'
             . esc_html__('Support', 'swapads-client') . '</a>';
        $h .= '</p>';
        $h .= '</div>';
        $h .= '</div>'; // close .swapads-page wrap
        return $h;
    }
}
