<?php
/**
 * Blokio theme functions.
 *
 * @package Blokio
 */

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

define('BLOKIO_VERSION', '1.0.1');

/**
 * Theme setup.
 */
function blokio_setup(): void
{
    add_theme_support('title-tag');
    add_theme_support('post-thumbnails');
    add_theme_support('automatic-feed-links');
    add_theme_support('responsive-embeds');
    add_theme_support('editor-styles');
    add_theme_support('wp-block-styles');
    add_theme_support('align-wide');
    add_theme_support('html5', [
        'search-form', 'comment-form', 'comment-list', 'gallery', 'caption', 'style', 'script',
    ]);

    // Block-based template parts (header/footer) come from theme.json's
    // templateParts — no register_nav_menus() needed for an FSE theme,
    // menus are managed as wp_navigation posts via the Site Editor.

    set_post_thumbnail_size(1200, 675, true);
    add_image_size('blokio-card', 640, 420, true);
    add_image_size('blokio-square', 480, 480, true);

    // WooCommerce: declare support and opt into wide/full alignment for
    // product grids rather than WooCommerce's own default markup.
    add_theme_support('woocommerce');
    add_theme_support('wc-product-gallery-zoom');
    add_theme_support('wc-product-gallery-lightbox');
    add_theme_support('wc-product-gallery-slider');

    load_theme_textdomain('blokio', get_template_directory() . '/languages');
}
add_action('after_setup_theme', 'blokio_setup');

/**
 * Register custom block pattern categories so Blokio's included patterns
 * group sensibly in the pattern inserter instead of dumping into
 * "Uncategorized".
 */
function blokio_register_pattern_categories(): void
{
    $categories = [
        'blokio-hero'     => __('Blokio: Hero', 'blokio'),
        'blokio-content'  => __('Blokio: Content Sections', 'blokio'),
        'blokio-cards'    => __('Blokio: Cards & Grids', 'blokio'),
        'blokio-social'   => __('Blokio: Social Proof', 'blokio'),
        'blokio-cta'      => __('Blokio: Calls to Action', 'blokio'),
        'blokio-single'   => __('Blokio: Single Post Components', 'blokio'),
    ];

    foreach ($categories as $slug => $label) {
        register_block_pattern_category($slug, ['label' => $label]);
    }
}
add_action('init', 'blokio_register_pattern_categories');

/**
 * Enqueue fonts and the (minimal) global stylesheet/script.
 *
 * Almost all visual design lives in theme.json, which WordPress compiles
 * to CSS custom properties and block styles automatically — style.css
 * here is intentionally small: only what theme.json cannot express
 * (animations, hover-state choreography, the destination-route signature
 * element, dark-mode overrides).
 */
function blokio_enqueue_assets(): void
{
    // Fonts (Poppins, Inter) are self-hosted via @font-face rules in
    // style.css and served from assets/fonts/ — WordPress.org guidelines
    // do not permit enqueueing fonts, scripts, or styles from third-party
    // servers/CDNs (including fonts.googleapis.com), for user privacy.
    wp_enqueue_style('blokio-style', get_stylesheet_uri(), [], BLOKIO_VERSION);

    wp_enqueue_script(
        'blokio-global',
        get_theme_file_uri('assets/js/global.js'),
        [],
        BLOKIO_VERSION,
        ['strategy' => 'defer', 'in_footer' => true]
    );
}
add_action('wp_enqueue_scripts', 'blokio_enqueue_assets');

/**
 * Applies a visitor's saved dark/light choice to <html> as early as
 * possible in <head> — before the stylesheet paints anything — so
 * returning visitors don't see a flash of the wrong theme. Falls
 * back to nothing (letting the prefers-color-scheme media query in
 * style.css take over) when no explicit choice has been saved yet.
 */
function blokio_theme_preference_script(): void
{
    ?>
<script>
(function(){try{var t=localStorage.getItem('blokio-theme');if(t==='dark'||t==='light'){document.documentElement.setAttribute('data-blokio-theme',t);}}catch(e){}})();
</script>
    <?php
}
add_action('wp_head', 'blokio_theme_preference_script', 1);

/**
 * Editor gets the same stylesheet so authoring previews match the
 * front end (colors, type scale, spacing).
 */
function blokio_editor_assets(): void
{
    add_editor_style('style.css');
}
add_action('after_setup_theme', 'blokio_editor_assets');

/**
 * Register a couple of block style variations so core blocks pick up
 * Blokio-specific looks directly from the block inserter/styles panel.
 */
function blokio_register_block_styles(): void
{
    register_block_style(
        'core/button',
        [
            'name'  => 'blokio-pill',
            'label' => __('Pill', 'blokio'),
        ]
    );

    register_block_style(
        'core/group',
        [
            'name'  => 'blokio-card',
            'label' => __('Blokio Card', 'blokio'),
        ]
    );
}
add_action('init', 'blokio_register_block_styles');

/**
 * Dynamic template components (reading time, breadcrumbs, share buttons,
 * related posts, author bio, copyright line).
 *
 * Template parts/templates in a block theme are static HTML — WordPress
 * never executes PHP inside them. To surface server-side logic there
 * without shortcodes (plugin-territory) or registering new block types
 * (also plugin-territory), each of these components is authored as an
 * ordinary core/paragraph or core/group block carrying an identifying
 * className, and its final HTML is swapped in via the `render_block`
 * filter — a standard content filter, not a new block registration.
 */
function blokio_render_dynamic_blocks(string $block_content, array $block): string
{
    if (empty($block['attrs']['className'])) {
        return $block_content;
    }

    $class_list = explode(' ', $block['attrs']['className']);

    if (in_array('blokio-reading-time', $class_list, true)) {
        return blokio_wrap_like($block_content, esc_html(blokio_get_reading_time()));
    }

    if (in_array('blokio-author-bio', $class_list, true) && is_author()) {
        $bio = get_the_author_meta('description');
        return '' === $bio ? '' : blokio_wrap_like($block_content, esc_html($bio));
    }

    if (in_array('blokio-breadcrumbs', $class_list, true)) {
        return blokio_wrap_like($block_content, blokio_breadcrumbs_markup());
    }

    if (in_array('blokio-related-posts', $class_list, true) && is_singular('post')) {
        $count = ! empty($block['attrs']['data-count']) ? (int) $block['attrs']['data-count'] : 3;
        return blokio_wrap_like($block_content, blokio_related_posts_markup($count));
    }

    if (in_array('blokio-copyright', $class_list, true)) {
        return blokio_wrap_like($block_content, blokio_copyright_markup());
    }

    return $block_content;
}
add_filter('render_block_core/paragraph', 'blokio_render_dynamic_blocks', 10, 2);
add_filter('render_block_core/group', 'blokio_render_dynamic_blocks', 10, 2);

/**
 * Swaps the inner content of a rendered core block's single wrapper tag
 * for $inner_html, keeping the block's own wrapper element/attributes
 * (and therefore any color/typography/spacing block supports the author
 * applied in the editor) intact.
 */
function blokio_wrap_like(string $block_content, string $inner_html): string
{
    $result = preg_replace('/(<[^>]+>)(.*)(<\/[^>]+>)\s*$/s', '$1' . $inner_html . '$3', $block_content, 1);

    return null === $result ? $block_content : $result;
}

/**
 * Estimated reading time — surfaced via the blokio-reading-time className.
 */
function blokio_get_reading_time(?int $post_id = null): string
{
    $post_id = $post_id ?: get_the_ID();

    if (! $post_id) {
        return '';
    }

    $content = get_post_field('post_content', $post_id);

    if (! is_string($content)) {
        return '';
    }

    $content    = wp_strip_all_tags(strip_shortcodes($content));
    $word_count = str_word_count($content);
    $minutes    = max(1, (int) ceil($word_count / 200));

    return sprintf(
        /* translators: %d: number of minutes */
        _n('%d min read', '%d ', $minutes, 'blokio'),
        $minutes
    );
}

/**
 * Lightweight breadcrumb trail, surfaced via the blokio-breadcrumbs
 * className.
 */
function blokio_breadcrumbs_markup(): string
{
    if (is_front_page()) {
        return '';
    }

    $crumbs   = [];
    $crumbs[] = sprintf('<a href="%s">%s</a>', esc_url(home_url('/')), esc_html__('Home', 'blokio'));

    if (is_singular('post')) {
        $categories = get_the_category();
        if (! empty($categories)) {
            $crumbs[] = sprintf(
                '<a href="%s">%s</a>',
                esc_url(get_category_link($categories[0]->term_id)),
                esc_html($categories[0]->name)
            );
        }
        $crumbs[] = esc_html(get_the_title());
    } elseif (is_category()) {
        $crumbs[] = esc_html(single_cat_title('', false));
    } elseif (is_search()) {
        $crumbs[] = esc_html__('Search results', 'blokio');
    } elseif (is_author()) {
        $crumbs[] = esc_html(get_the_author());
    } elseif (is_page()) {
        $crumbs[] = esc_html(get_the_title());
    }

    if (empty($crumbs)) {
        return '';
    }

    return implode(' <span aria-hidden="true">/</span> ', $crumbs);
}

/**
 * Related posts (by shared category) — surfaced via the
 * blokio-related-posts className.
 */
function blokio_related_posts_markup(int $count = 3): string
{
    $post_id    = get_the_ID();
    $categories = wp_get_post_categories($post_id);

    if (empty($categories)) {
        return '';
    }

    $related = new WP_Query([
        'category__in'        => $categories,
        'post__not_in'        => [$post_id],
        'posts_per_page'      => $count,
        'ignore_sticky_posts' => true,
        'no_found_rows'       => true,
    ]);

    if (! $related->have_posts()) {
        wp_reset_postdata();
        return '';
    }

    $items = '';
    while ($related->have_posts()) {
        $related->the_post();
        $thumb  = has_post_thumbnail() ? '<div class="blokio-related-posts__thumb">' . get_the_post_thumbnail(get_the_ID(), 'blokio-square') . '</div>' : '';
        $items .= sprintf(
            '<a class="blokio-related-posts__item" href="%s">%s<span class="blokio-related-posts__title">%s</span></a>',
            esc_url(get_permalink()),
            $thumb,
            esc_html(get_the_title())
        );
    }
    wp_reset_postdata();

    return $items;
}

/**
 * Copyright line for the footer — surfaced via the blokio-copyright
 * className.
 */
function blokio_copyright_markup(): string
{
    $custom = trim((string) get_theme_mod('blokio_copyright_text', ''));
    $year   = wp_date('Y');

    if ('' !== $custom) {
        return esc_html(
            str_replace('{year}', $year, $custom)
        );
    }

    return sprintf(
        '&copy; %1$s %2$s. %3$s',
        esc_html($year),
        esc_html(get_bloginfo('name')),
        esc_html__('All rights reserved.', 'blokio')
    );
}

/**
 * Renders the primary category as a small badge — used in blog-card
 * patterns.
 */
function blokio_category_badge(?int $post_id = null): string
{
    $post_id    = $post_id ?: get_the_ID();
    $categories = get_the_category($post_id);

    if (empty($categories)) {
        return '';
    }

    return sprintf(
        '<span class="blokio-badge">%s</span>',
        esc_html($categories[0]->name)
    );
}

/**
 * Adds a "Footer" Customizer section with a single text control for the
 * copyright line — otherwise there was no way for a site owner to set
 * their own copyright text at all (blokio_copyright_markup() only ever
 * auto-generated "© {year} {site name}. All rights reserved.").
 * Leaving the field blank keeps the auto-generated text; {year} in a
 * custom value is replaced with the current year automatically, so a
 * custom copyright line still stays up to date without editing it
 * every January.
 */
function blokio_customize_register(\WP_Customize_Manager $wp_customize): void
{
    $wp_customize->add_section('blokio_footer', [
        'title'    => __('Footer', 'blokio'),
        'priority' => 160,
    ]);

    $wp_customize->add_setting('blokio_copyright_text', [
        'default'           => '',
        'sanitize_callback' => 'sanitize_text_field',
        'transport'         => 'refresh',
    ]);

    $wp_customize->add_control('blokio_copyright_text', [
        'type'        => 'text',
        'section'     => 'blokio_footer',
        'label'       => __('Copyright text', 'blokio'),
        'description' => __('Leave blank to use "© {year} Site Name. All rights reserved." automatically. Otherwise, type your own text — use {year} anywhere to insert the current year.', 'blokio'),
    ]);
}
add_action('customize_register', 'blokio_customize_register');

