<?php
/**
 * Twig Template Context Builder.
 *
 * Gathers WordPress data into structured arrays for Twig templates.
 *
 * @package WPBootstrap
 * @since 0.1.1
 */

namespace WPBootstrap\Template;

class ContextBuilder
{
    private NavWalker $navWalker;

    public function __construct()
    {
        $this->navWalker = new NavWalker();
    }

    /**
     * Build the complete context for the current request.
     */
    public function build(): array
    {
        $context = [
            'site'           => $this->getSiteData(),
            'menu'           => $this->getMenuData('primary'),
            'footer_menu'    => $this->getMenuData('footer'),
            'dark_mode'      => true,
            'layout'         => 'default',
            'header_variant' => $this->getHeaderVariant(),
            'footer_variant' => $this->getFooterVariant(),
        ];

        if (is_singular()) {
            $context['post'] = $this->getPostData();

            if (is_singular('post')) {
                $context['comments']        = $this->getCommentsData();
                $context['post_navigation'] = $this->getPostNavigation();
                $context['more_posts']      = $this->getMorePosts();
            }
        }

        if (is_home() || is_archive() || is_search()) {
            $context['posts']      = $this->getPostsLoop();
            $context['pagination'] = $this->getPagination();
        }

        if (is_archive()) {
            $context['archive'] = $this->getArchiveData();
        }

        if (is_search()) {
            $context['search_query'] = get_search_query();
        }

        // Sidebar layout detection.
        if (is_home()) {
            $pageId = (int) get_option('page_for_posts');
            if ($pageId) {
                $templateSlug = get_page_template_slug($pageId);
                if ($templateSlug === 'home-sidebar') {
                    $context['layout'] = 'sidebar';
                }
            }
            $context['sidebar'] = $this->getSidebarData();
        }

        return $context;
    }

    /**
     * Get global site information.
     */
    private function getSiteData(): array
    {
        return [
            'name'        => get_bloginfo('name'),
            'description' => get_bloginfo('description'),
            'url'         => home_url('/'),
            'charset'     => get_bloginfo('charset'),
        ];
    }

    /**
     * Get navigation menu items for a location.
     */
    private function getMenuData(string $location): array
    {
        $locations = get_nav_menu_locations();

        if (isset($locations[$location])) {
            $menu = wp_get_nav_menu_object($locations[$location]);
            if ($menu) {
                $items = wp_get_nav_menu_items($menu->term_id);
                if ($items) {
                    return $this->navWalker->buildTree($items);
                }
            }
        }

        // Fallback for primary: list top-level pages.
        if ($location === 'primary') {
            return $this->getPagesFallback();
        }

        return [];
    }

    /**
     * Fallback menu from published pages.
     */
    private function getPagesFallback(): array
    {
        $pages = get_pages([
            'sort_column' => 'menu_order,post_title',
            'parent'      => 0,
        ]);

        $items = [];
        foreach ($pages as $page) {
            $items[] = [
                'id'       => $page->ID,
                'title'    => $page->post_title,
                'url'      => get_permalink($page->ID),
                'target'   => '',
                'classes'  => '',
                'active'   => is_page($page->ID),
                'children' => [],
            ];
        }

        return $items;
    }

    /**
     * Get single post/page data.
     */
    private function getPostData(): array
    {
        global $post;

        return [
            'id'         => $post->ID,
            'title'      => get_the_title(),
            'url'        => get_permalink(),
            'content'    => apply_filters('the_content', get_the_content()),
            'excerpt'    => get_the_excerpt(),
            'date'       => get_the_date(),
            'date_iso'   => get_the_date('c'),
            'modified'   => get_the_modified_date(),
            'author'     => [
                'name' => get_the_author(),
                'url'  => get_author_posts_url(get_the_author_meta('ID')),
            ],
            'thumbnail'  => get_the_post_thumbnail_url($post->ID, 'large') ?: '',
            'categories' => $this->getTermsList('category'),
            'tags'       => $this->getTermsList('post_tag'),
            'type'       => get_post_type(),
        ];
    }

    /**
     * Get posts for the main query loop.
     */
    private function getPostsLoop(): array
    {
        global $wp_query;
        $posts = [];

        if ($wp_query->have_posts()) {
            while ($wp_query->have_posts()) {
                $wp_query->the_post();
                $posts[] = [
                    'id'        => get_the_ID(),
                    'title'     => get_the_title(),
                    'url'       => get_permalink(),
                    'excerpt'   => get_the_excerpt(),
                    'date'      => get_the_date(),
                    'date_iso'  => get_the_date('c'),
                    'author'    => [
                        'name' => get_the_author(),
                        'url'  => get_author_posts_url(get_the_author_meta('ID')),
                    ],
                    'thumbnail' => get_the_post_thumbnail_url(null, 'medium_large') ?: '',
                    'categories' => $this->getTermsList('category'),
                    'tags'       => $this->getTermsList('post_tag'),
                    'read_more' => __('Read more', 'wp-bootstrap'),
                ];
            }
            wp_reset_postdata();
        }

        return $posts;
    }

    /**
     * Build pagination data.
     */
    private function getPagination(): array
    {
        global $wp_query;

        $totalPages  = (int) $wp_query->max_num_pages;
        $currentPage = max(1, get_query_var('paged'));

        if ($totalPages <= 1) {
            return [];
        }

        $pages = [];
        for ($i = 1; $i <= $totalPages; $i++) {
            $pages[] = [
                'number'     => $i,
                'url'        => get_pagenum_link($i),
                'is_current' => ($i === $currentPage),
            ];
        }

        return [
            'pages'     => $pages,
            'current'   => $currentPage,
            'total'     => $totalPages,
            'prev_url'  => ($currentPage > 1) ? get_pagenum_link($currentPage - 1) : null,
            'next_url'  => ($currentPage < $totalPages) ? get_pagenum_link($currentPage + 1) : null,
            'prev_text' => __('Previous', 'wp-bootstrap'),
            'next_text' => __('Next', 'wp-bootstrap'),
        ];
    }

    /**
     * Get archive page data.
     */
    private function getArchiveData(): array
    {
        return [
            'title'       => get_the_archive_title(),
            'description' => get_the_archive_description(),
        ];
    }

    /**
     * Get comments for the current post.
     */
    private function getCommentsData(): array
    {
        $postId = get_the_ID();
        $count  = (int) get_comments_number($postId);

        $comments = get_comments([
            'post_id' => $postId,
            'status'  => 'approve',
            'orderby' => 'comment_date_gmt',
            'order'   => 'ASC',
        ]);

        return [
            'list'    => $this->buildCommentTree($comments),
            'count'   => $count,
            'title'   => sprintf(
                _n('%s Comment', '%s Comments', $count, 'wp-bootstrap'),
                number_format_i18n($count)
            ),
            'form'    => $this->getCommentFormHtml(),
            'is_open' => comments_open($postId),
        ];
    }

    /**
     * Build a nested comment tree from flat comments.
     */
    private function buildCommentTree(array $comments, int $parentId = 0): array
    {
        $tree = [];

        foreach ($comments as $comment) {
            if ((int) $comment->comment_parent !== $parentId) {
                continue;
            }

            $tree[] = [
                'id'         => (int) $comment->comment_ID,
                'author'     => $comment->comment_author,
                'author_url' => $comment->comment_author_url,
                'avatar_url' => get_avatar_url($comment, ['size' => 40]),
                'date'       => get_comment_date('', $comment),
                'date_iso'   => get_comment_date('c', $comment),
                'content'    => apply_filters('comment_text', $comment->comment_content, $comment),
                'edit_url'   => current_user_can('edit_comment', $comment->comment_ID)
                    ? get_edit_comment_link($comment)
                    : '',
                'reply_url'  => get_comment_reply_link([
                    'depth'     => 1,
                    'max_depth' => get_option('thread_comments_depth', 5),
                ], $comment),
                'children'   => $this->buildCommentTree($comments, (int) $comment->comment_ID),
            ];
        }

        return $tree;
    }

    /**
     * Capture the WordPress comment form HTML.
     */
    private function getCommentFormHtml(): string
    {
        if (! comments_open()) {
            return '';
        }

        ob_start();
        comment_form([
            'title_reply'          => __('Leave a Comment', 'wp-bootstrap'),
            'title_reply_before'   => '<h3 id="reply-title" class="comment-reply-title h5 mb-3">',
            'title_reply_after'    => '</h3>',
            'class_form'           => 'needs-validation',
            'class_submit'         => 'btn btn-primary',
            'submit_button'        => '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />',
            'comment_field'        => '<div class="mb-3"><label for="comment" class="form-label">' . __('Comment', 'wp-bootstrap') . '</label><textarea id="comment" name="comment" class="form-control" rows="5" required></textarea></div>',
        ]);
        return ob_get_clean();
    }

    /**
     * Get previous/next post navigation.
     */
    private function getPostNavigation(): array
    {
        $prev = get_previous_post();
        $next = get_next_post();

        $navigation = [];

        if ($prev) {
            $navigation['previous'] = [
                'title' => get_the_title($prev),
                'url'   => get_permalink($prev),
            ];
        }

        if ($next) {
            $navigation['next'] = [
                'title' => get_the_title($next),
                'url'   => get_permalink($next),
            ];
        }

        return $navigation;
    }

    /**
     * Get recent posts for the "More posts" section.
     */
    private function getMorePosts(int $count = 3): array
    {
        $currentId = get_the_ID();

        $query = new \WP_Query([
            'posts_per_page' => $count,
            'post__not_in'   => [$currentId],
            'orderby'        => 'date',
            'order'          => 'DESC',
        ]);

        $posts = [];
        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();
                $posts[] = [
                    'id'        => get_the_ID(),
                    'title'     => get_the_title(),
                    'url'       => get_permalink(),
                    'date'      => get_the_date(),
                    'date_iso'  => get_the_date('c'),
                    'thumbnail' => get_the_post_thumbnail_url(null, 'medium_large') ?: '',
                ];
            }
            wp_reset_postdata();
        }

        return $posts;
    }

    /**
     * Get sidebar widget data.
     *
     * If the 'primary-sidebar' widget area has widgets assigned,
     * their rendered HTML is returned. Otherwise, fallback data
     * (recent posts, tags) is provided for the default Twig sidebar.
     */
    private function getSidebarData(): array
    {
        $widgets_active = is_active_sidebar( 'primary-sidebar' );
        $widgets_html   = '';
        if ( $widgets_active ) {
            ob_start();
            dynamic_sidebar( 'primary-sidebar' );
            $widgets_html = ob_get_clean();
        }

        return [
            'widgets_active' => $widgets_active,
            'widgets_html'   => $widgets_html,
            'recent_posts'   => $this->getSidebarRecentPosts(),
            'tags'           => $this->getSidebarTags(),
        ];
    }

    /**
     * Get recent posts for sidebar.
     */
    private function getSidebarRecentPosts(int $count = 4): array
    {
        $query = new \WP_Query([
            'posts_per_page' => $count,
            'orderby'        => 'date',
            'order'          => 'DESC',
        ]);

        $posts = [];
        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();
                $posts[] = [
                    'title' => get_the_title(),
                    'url'   => get_permalink(),
                    'date'  => get_the_date(),
                ];
            }
            wp_reset_postdata();
        }

        return $posts;
    }

    /**
     * Get tags for sidebar tag cloud.
     */
    private function getSidebarTags(int $count = 15): array
    {
        $tags = get_tags([
            'number'  => $count,
            'orderby' => 'count',
            'order'   => 'DESC',
        ]);

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

        $items = [];
        foreach ($tags as $tag) {
            $items[] = [
                'name'  => $tag->name,
                'url'   => get_tag_link($tag->term_id),
                'count' => $tag->count,
            ];
        }

        return $items;
    }

    /**
     * Get the active header variant.
     *
     * @since 0.2.0
     */
    private function getHeaderVariant(): string
    {
        return get_theme_mod('wp_bootstrap_header_variant', 'default');
    }

    /**
     * Get the active footer variant.
     *
     * @since 0.2.0
     */
    private function getFooterVariant(): string
    {
        return get_theme_mod('wp_bootstrap_footer_variant', 'default');
    }

    /**
     * Get terms list for a taxonomy.
     */
    private function getTermsList(string $taxonomy): array
    {
        $terms = get_the_terms(get_the_ID(), $taxonomy);
        if (! $terms || is_wp_error($terms)) {
            return [];
        }

        $list = [];
        foreach ($terms as $term) {
            $list[] = [
                'name' => $term->name,
                'url'  => get_term_link($term),
            ];
        }

        return $list;
    }
}
