<?php
/**
 * Forumax theme helper functions and resources
 */
if ( !class_exists( 'Forumax_Forum_Class' ) ) {
    class Forumax_Forum_Class {
        /**
         * Hold an instance of Forumax_Forum_Class class.
         * @var Forumax_Forum_Class
         */
        protected static $instance = null;

        /**
         * Main Forumax_Forum_Class instance.
         * @return Forumax_Forum_Class - Main instance.
         */
        public static function instance() {

            if ( null === self::$instance ) {
                self::$instance = new Forumax_Forum_Class();
            }

            return self::$instance;
        }
        /**
         * Adds a reference of this object to $instance, populates default strings,
         * @see __construct
         */
        public function __construct() {
            add_filter( 'the_posts', [ $this, 'inject_sticky_topics' ], 10, 2 );

            // Cache invalidation hooks
            add_action( 'bbp_new_topic', [ $this, 'invalidate_forum_caches' ], 10, 2 );
            add_action( 'bbp_edit_topic', [ $this, 'invalidate_forum_caches' ], 10, 2 );
            add_action( 'bbp_closed_topic', [ $this, 'invalidate_forum_caches' ], 10, 2 );
            add_action( 'bbp_opened_topic', [ $this, 'invalidate_forum_caches' ], 10, 2 );
            add_action( 'bbp_trash_topic', [ $this, 'maybe_invalidate_forum_caches' ] );
            add_action( 'bbp_untrash_topic', [ $this, 'maybe_invalidate_forum_caches' ] );
            add_action( 'bbp_deleted_topic', [ $this, 'maybe_invalidate_forum_caches' ] );
        }

        /**
         * Authors Name
         *
         * @return string
         */
        public static function forum_topics_authors() {
            global $wpdb;

            $forum_id = get_queried_object_id();
            $cache_key = 'frmx_authors_data_' . $forum_id;
            $display_authors = get_transient( $cache_key );

            if ( false === $display_authors ) {
                $d_users = [];
                $forumusers = get_users();

                if ( $forumusers ) {
                    foreach ( $forumusers as $forumuser ) {
                        $post_count = count_user_posts( $forumuser->ID, 'topic' );
                        $d_users[$forumuser->ID] = $post_count;
                    }
                    arsort( $d_users );

                    // Optimization: Fetch all counts for the current parent in one query
                    $author_counts = [];
                    if ( ! empty( $d_users ) ) {
                        $sql = $wpdb->prepare( "
                            SELECT post_author, COUNT(*) as count
                            FROM $wpdb->posts
                            WHERE post_type = 'topic'
                            AND post_status = 'publish'
                            AND post_parent = %d
                            GROUP BY post_author
                        ", $forum_id );

                        $results = $wpdb->get_results( $sql );
                        if ( $results ) {
                            foreach ( $results as $row ) {
                                $author_counts[ $row->post_author ] = $row->count;
                            }
                        }
                    }

                    $display_authors = [];
                    foreach ( $d_users as $key => $value ) {
                        // Use pre-fetched count
                        $users_post_count = isset( $author_counts[ $key ] ) ? $author_counts[ $key ] : 0;

                        if ( $users_post_count > 0 ) {
                            $display_authors[] = [
                                'ID'    => $key,
                                'count' => $users_post_count
                            ];
                        }
                    }

                    set_transient( $cache_key, $display_authors, HOUR_IN_SECONDS );
                }
            }

            if ( ! empty( $display_authors ) ) {
                foreach ( $display_authors as $author_data ) {
                    $user_id = $author_data['ID'];
                    $user    = get_userdata( $user_id );

                    if ( ! $user ) {
                        continue;
                    }

                    $post_count = $author_data['count'];

                    echo '<div class="userlist">';
                    echo '<a class="frmx-dropdown-item current-user forumax-data data-auth" data-nonce="' . wp_create_nonce( 'forumax-nonce' ) . '" data-rel="' . esc_attr( $user->display_name ) . '" data-type="author" data-count="' . esc_attr( $post_count ) . '" data-parent="' . esc_attr( $forum_id ) . '" data-id="' . intval( $user_id ) . '" href="#' . esc_attr( $user->display_name ) . '">
                            <img src="' . esc_url( get_avatar_url( $user_id ) ) . '" alt="' . esc_attr( $user->display_name ) . '">' . esc_html( $user->display_name ) . '<span class="count">' . esc_html( $post_count ) . '</span>
                          </a>';
                    echo '</div>';
                }
            }
        }

        /**
         * Tag Name
         *
         * @return string
         */
        public static function forum_topics_tags() {
            global $wpdb;

            $forum_id = get_queried_object_id();
            $cache_key = 'frmx_tags_data_' . $forum_id;
            $tags = get_transient( $cache_key );

            if ( false === $tags ) {
                $tags = $wpdb->get_results( $wpdb->prepare(
                    "SELECT DISTINCT t.term_id, t.name, t.slug, tt.count
                    FROM {$wpdb->terms} AS t
                    INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
                    INNER JOIN {$wpdb->term_relationships} AS tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
                    INNER JOIN {$wpdb->posts} AS p ON tr.object_id = p.ID
                    WHERE tt.taxonomy = 'topic-tag'
                    AND p.post_type = 'topic'
                    AND p.post_parent = %d
                    AND p.post_status = 'publish'
                    ORDER BY t.name ASC",
                    $forum_id
                ) );

                set_transient( $cache_key, $tags, HOUR_IN_SECONDS );
            }

            if ( $tags ) {
                foreach ( $tags as $tag ) {
                    $post_count = $tag->count;
                    echo '<div class="tagList" id="' . esc_attr( $tag->slug ) . '">';
                    echo '<a class="frmx-dropdown-item forumax-data data-tag" data-parent="' . esc_attr( $forum_id ) . '" data-nonce="' . wp_create_nonce( 'forumax-nonce' ) . '" data-rel="' . esc_attr( $tag->slug ) . '" data-type="tag" data-count="' . esc_attr( $post_count ) . '" data-id="' . intval( $tag->term_id ) . '" href="#' . esc_attr( $tag->slug ) . '"><span class="color-purple"></span>' . esc_html( $tag->name ) . '</a>';
                    echo '</div>';
                }
            }
        }

        /**
         * Invalidate forum caches when a topic is updated.
         *
         * @param int $topic_id Topic ID.
         * @param int $forum_id Optional. Forum ID.
         */
        public function invalidate_forum_caches( $topic_id, $forum_id = 0 ) {
            if ( ! $forum_id ) {
                $forum_id = bbp_get_topic_forum_id( $topic_id );
            }

            if ( $forum_id ) {
                delete_transient( 'frmx_authors_data_' . $forum_id );
                delete_transient( 'frmx_tags_data_' . $forum_id );
                delete_transient( 'frmx_topic_count_publish_' . $forum_id );
                delete_transient( 'frmx_topic_count_closed_' . $forum_id );

                // Also invalidate global topic counts (forum_id = 0) used on main archive
                delete_transient( 'frmx_topic_count_publish_0' );
                delete_transient( 'frmx_topic_count_closed_0' );
            }
        }

        /**
         * Maybe invalidate forum caches when a post is trashed/untrashed/deleted.
         *
         * @param int $post_id Post ID.
         */
        public function maybe_invalidate_forum_caches( $post_id ) {
            if ( 'topic' === get_post_type( $post_id ) ) {
                $this->invalidate_forum_caches( $post_id );
            }
        }

        /**
         * Tag Name
         *
         * @return void
         */
        public static function forum_topics_open_close(): void
        {
            $is_queried_obj = is_singular('forum') ? get_queried_object_id() : false;
            $user_id = is_singular('forum') ? false : bbp_get_displayed_user_field('ID');

            // Get the active tab from the URL or default to 'open'
            $active_tab = isset($_GET['tab']) && in_array($_GET['tab'], ['open', 'closed'], true) ? sanitize_text_field($_GET['tab']) : 'open';

            // Count open and closed topics efficiently
            $open_count = forumax_get_topic_count_by_status('publish', $is_queried_obj);
            $closed_count = forumax_get_topic_count_by_status('closed', $is_queried_obj);

            if ( in_array('bbp-user-page', get_body_class(), true) ) :
                ?>
                <ul class="support-total-info">
                    <li class="open-ticket">
                        <?php esc_html_e( 'TOPIC', 'forumax' ); ?>
                    </li>
                </ul>
                <ul class="category-menu">
                    <li> <?php esc_html_e( 'Comments', 'forumax' ); ?> </li>
                    <li> <?php esc_html_e( 'Favorites', 'forumax' ); ?> </li>
                </ul>
            <?php
            else :
                ?>
                <ul class="support-total-info">
                    <li class="open-ticket <?php echo 'open' === $active_tab ? 'active' : ''; ?>">
                        <i class="icon_info_alt"></i>
                        <a href="?tab=open"
                           class="open-data"
                           data-nonce="<?php echo wp_create_nonce( 'forumax-nonce' );?>"
                           data-type="open"
                           data-userid="<?php echo esc_attr($user_id); ?>"
                           data-parent="<?php echo esc_attr($is_queried_obj); ?>">
                            <?php echo esc_html($open_count) . esc_html__(' Open', 'forumax'); ?>
                        </a>
                    </li>
                    <li class="close-ticket <?php echo 'closed' === $active_tab ? 'active' : ''; ?>">
                        <i class="icon_check"></i>
                        <a href="?tab=closed"
                           class="open-data"
                           data-nonce="<?php echo wp_create_nonce( 'forumax-nonce' );?>"
                           data-type="closed"
                           data-parent="<?php echo esc_attr($is_queried_obj); ?>"
                           data-userid="<?php echo esc_attr($user_id); ?>">
                            <?php echo esc_html($closed_count) . esc_html__(' Closed', 'forumax'); ?>
                        </a>
                    </li>
                </ul>
            <?php
            endif;
        }

        function topic_badges() {
            if( bbp_is_topic_sticky(get_the_ID()) ) { ?>
                <span class="badge badge-success">
            <?php esc_html_e( 'Sticky', 'forumax' ); ?>
        </span>
            <?php }
            if ( bbp_is_topic_closed( get_the_ID() ) ) { ?>
                <span class="badge badge-danger">
                    <?php esc_html_e( 'Closed', 'forumax' ); ?>
                </span>
            <?php }
        }

        /**
         * Inject sticky topics into the main topic loop
         *
         * @param array    $posts The array of retrieved posts.
         * @param WP_Query $query The WP_Query instance.
         */
        public function inject_sticky_topics( $posts, $query ) {
            if ( is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
                return $posts;
            }

            // Identify the target query: Topics ordered by ID (as in loop-topics.php )
            if ( $query->get( 'post_type' ) !== 'topic' || $query->get( 'orderby' ) !== 'ID' ) {
                return $posts;
            }

            // Only on first page
            if ( $query->get( 'paged' ) > 1 ) {
                return $posts;
            }

            // Prevent recursion
            remove_filter( 'the_posts', [$this, 'inject_sticky_topics'], 10 );

            $sticky_ids = [];

            // Get Super Stickies
            $super_stickies = bbp_get_super_stickies();

            // Get Forum Stickies
            $forum_id = 0;
            if ( is_singular( 'forum' ) ) {
                $forum_id = get_queried_object_id();
            } elseif ( $query->get( 'post_parent' ) ) {
                $post_parent = $query->get( 'post_parent' );
                if ( is_numeric( $post_parent ) && $post_parent > 0 ) {
                    $forum_id = $post_parent;
                }
            }

            $stickies = bbp_get_stickies( $forum_id );

            $sticky_ids = array_unique(array_merge( $super_stickies, $stickies ) );

            if ( ! empty( $sticky_ids ) ) {
                $sticky_args = [
                    'post_type' => 'topic',
                    'post_parent' => 'any',
                    'post__in' => $sticky_ids,
                    'posts_per_page' => -1,
                    'orderby' => 'post__in',
                    'ignore_sticky_posts' => 1,
                    'no_found_rows' => true,
                ];

                $sticky_query = new WP_Query( $sticky_args );

                if ( $sticky_query->have_posts() ) {
                    $sticky_posts = $sticky_query->posts;

                    // Filter out stickies from the main posts to avoid duplicates
                    $posts = array_filter( $posts, function ( $p ) use ( $sticky_ids ) {
                        return !in_array( $p->ID, $sticky_ids, true );
                    });

                    // Prepend stickies
                    $posts = array_merge( $sticky_posts, $posts );
                }
            }

            add_filter( 'the_posts', [ $this, 'inject_sticky_topics'], 10, 2 );

            return $posts;
        }
    }
}

/**
 * Get Forumax Forum Class instance
 * Works with or without Forumax theme active
 * 
 * @return Forumax_Forum_Class|null
 */
if ( ! function_exists( 'Forumax_Forum' ) ) {
	function Forumax_Forum() {
		if ( class_exists( 'Forumax_Forum_Class' ) ) {
			return Forumax_Forum_Class::instance();
		}
		return null;
	}
}
