<?php
declare(strict_types=1);

if (!defined('ABSPATH')) { exit; }

/**
 * Posts block — lists published blog posts (pages with type='post'),
 * newest first, as a responsive card grid. Author-facing on any client
 * site: drop it on a /blog page and it auto-populates as posts are
 * published. The post body itself renders via the normal page renderer
 * at /:slug, so this block only needs the index listing.
 *
 * Settings (el['settings']):
 *   heading      string  optional H2 above the grid
 *   columns      int     1-3, default 2
 *   limit        int     max posts, default 12
 *   show_date    bool    default true
 *   show_excerpt bool    default true
 *   empty_text   string  shown when there are no posts yet
 *
 * Returns inner HTML (no `.impulse-el` wrapper — the caller adds it).
 */
function impulse_element_render_posts($el, array $settings, string $context): string
{
    if (is_object($el)) $el = (array) $el;
    $s        = (array) ($el['settings'] ?? []);
    $heading  = trim((string) ($s['heading'] ?? ''));
    $columns  = max(1, min(3, (int) ($s['columns'] ?? 2)));
    $limit    = max(1, (int) ($s['limit'] ?? 12));
    $showDate = !isset($s['show_date'])    || $s['show_date']    === true || $s['show_date']    === '1' || $s['show_date']    === 1;
    $showExc  = !isset($s['show_excerpt']) || $s['show_excerpt'] === true || $s['show_excerpt'] === '1' || $s['show_excerpt'] === 1;
    $emptyTxt = trim((string) ($s['empty_text'] ?? 'No posts yet. Check back soon.'));

    $posts = \Instinctor\Services\PageService::getPublishedPosts($limit);

    // Scope styles to this element instance so multiple Posts blocks (or the
    // editor preview) never bleed into each other.
    $uid = preg_replace('/[^a-z0-9_-]/i', '', (string) ($el['id'] ?? 'posts'));
    $wrap = 'imp-posts-' . $uid;

    // Explicit, self-contained colours so the index reads cleanly on any page
    // background (a blog index is dark-on-light regardless of the site theme).
    $cssInner = ".{$wrap}{width:100%;box-sizing:border-box}"
        . ".{$wrap} .imp-posts-heading{color:#1d2327}"
        . ".{$wrap} .imp-posts-grid{display:grid;grid-template-columns:repeat({$columns},1fr);gap:20px}"
        . ".{$wrap} .imp-post-card{display:flex;flex-direction:column;text-decoration:none;color:#1d2327;background:#ffffff;border:1px solid #e0e0e0;border-radius:3px;overflow:hidden;transition:transform .18s ease-in-out,box-shadow .18s ease-in-out}"
        . ".{$wrap} .imp-post-card:hover{transform:translateY(-3px);box-shadow:0 10px 30px rgba(0,0,0,0.12)}"
        . ".{$wrap} .imp-post-thumb{width:100%;aspect-ratio:16/9;object-fit:cover;display:block;background:#f0f0f0}"
        . ".{$wrap} .imp-post-body{padding:18px 20px;display:flex;flex-direction:column;gap:8px}"
        . ".{$wrap} .imp-post-date{font-size:12px;letter-spacing:0.05em;text-transform:uppercase;color:#999}"
        . ".{$wrap} .imp-post-title{font-size:20px;line-height:1.25;font-weight:700;margin:0;color:#1d2327}"
        . ".{$wrap} .imp-post-excerpt{font-size:14px;line-height:1.55;color:#555;margin:0 0 12px;height:150px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:#e0e0e0 transparent}"
        . ".{$wrap} .imp-posts-empty{color:#888;padding:40px 0;text-align:center}"
        . "@media (max-width:760px){.{$wrap} .imp-posts-grid{grid-template-columns:1fr}}";
    wp_add_inline_style('instinctor-page-inline', $cssInner);

    $h  = '<div class="' . $wrap . '">';
    if ($heading !== '') {
        $h .= '<h2 class="imp-posts-heading" style="margin:0 0 18px">' . esc_html($heading) . '</h2>';
    }

    if (empty($posts)) {
        $h .= '<div class="imp-posts-empty">' . esc_html($emptyTxt) . '</div></div>';
        return $h;
    }

    $h .= '<div class="imp-posts-grid">';
    foreach ($posts as $p) {
        $url = '/' . ltrim((string) $p['slug'], '/');
        $h .= '<a class="imp-post-card" href="' . esc_url($url) . '">';
        if (!empty($p['image'])) {
            $h .= '<img class="imp-post-thumb" src="' . esc_url((string) $p['image']) . '" alt="' . esc_attr((string) $p['title']) . '" loading="lazy">';
        }
        $h .= '<div class="imp-post-body">';
        if ($showDate && !empty($p['date'])) {
            $ts = strtotime((string) $p['date']);
            $h .= '<span class="imp-post-date">' . esc_html($ts ? gmdate('F j, Y', $ts) : (string) $p['date']) . '</span>';
        }
        $h .= '<h3 class="imp-post-title">' . esc_html((string) $p['title']) . '</h3>';
        if ($showExc && !empty($p['excerpt'])) {
            $h .= '<p class="imp-post-excerpt">' . esc_html((string) $p['excerpt']) . '</p>';
        }
        // No "Read" affordance: the whole card is the <a>, so the arrow repeated
        // what the cursor already says. /directory carries a button because its
        // cards are not themselves links. Sergei 2026-08-11.
        $h .= '</div></a>';
    }
    $h .= '</div></div>';

    return $h;
}
