<?php

namespace Datalumo\Sync;

use WP_Post;

class EntryPreparer
{
    public function prepare(WP_Post $post, array $metaMappings = []): ?array
    {
        // Avoid the full 'the_content' filter chain which may assume
        // a frontend request context (e.g. enqueuing scripts, global
        // post state).  Apply only the core WordPress formatting
        // filters that are safe in a background / CLI context.
        //
        // Shortcodes are stripped by default: they typically render
        // widgets/forms/galleries rather than body text, and in a
        // background context they lack the request globals (current
        // query, user, loop state) they expect — producing wrong or
        // empty output that gets indexed as truth. Sites with
        // shortcodes that emit meaningful text can opt in via the
        // `datalumo_render_shortcodes` filter.
        $content = $post->post_content;
        $content = apply_filters('datalumo_render_shortcodes', false, $post)
            ? do_shortcode($content)
            : strip_shortcodes($content);
        $content = wpautop($content);
        $content = do_blocks($content);
        $content = wptexturize($content);
        $content = wp_filter_content_tags($content);

        if (empty(trim(wp_strip_all_tags($content)))) {
            return null;
        }

        $meta = [
            'post_type'    => $post->post_type,
            'categories'   => $this->getTermSlugs($post->ID, 'category'),
            'tags'         => $this->getTermSlugs($post->ID, 'post_tag'),
            'author'       => get_the_author_meta('display_name', $post->post_author),
            'published_at' => $post->post_date,
            'modified_at'  => $post->post_modified,
        ];

        $searchableMeta = [];

        foreach ($metaMappings as $mapping) {
            $name = $mapping['name'] ?? '';
            $type = $mapping['type'] ?? '';
            $source = $mapping['source'] ?? '';
            $searchable = ! empty($mapping['searchable']);

            if (empty($name) || empty($source)) {
                continue;
            }

            $value = $this->resolveMapping($post, $type, $source);

            if ($value === null || $value === '' || $value === []) {
                continue;
            }

            if ($searchable) {
                $searchableMeta[$name] = $value;
            } else {
                $meta[$name] = $value;
            }
        }

        $entry = [
            'raw_text'    => $content,
            'title'       => $post->post_title,
            'source_type' => 'wordpress',
            'source_id'   => (string) $post->ID,
            'source_url'  => get_permalink($post->ID),
            'meta'        => $meta,
        ];

        if (! empty($searchableMeta)) {
            $entry['searchable_meta'] = $searchableMeta;
        }

        return $entry;
    }

    private function resolveMapping(WP_Post $post, string $type, string $source): mixed
    {
        if ($type === 'taxonomy') {
            return $this->getTermSlugs($post->ID, $source);
        }

        if ($type === 'post_meta') {
            return get_post_meta($post->ID, $source, true);
        }

        return null;
    }

    private function getTermSlugs(int $postId, string $taxonomy): array
    {
        $terms = get_the_terms($postId, $taxonomy);

        if (! $terms || is_wp_error($terms)) {
            return [];
        }

        return wp_list_pluck($terms, 'slug');
    }
}
