<?php

namespace Fab\Controller;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

use Fab\Metabox\FABMetaboxSetting;
use Fab\Interfaces\JIT_Interface;
use Fab\Helper\FABModal;

/**
 * Social Sharing Frontend.
 *
 * @package    Fab
 * @subpackage Fab/Module
 */
class Related_Post_Frontend extends Related_Post_Type implements JIT_Interface {

    /**
     * Add post recommendation data to FAB item
     *
     * @param object $instance FAB item instance.
     * @return void
     */
    public function add_fab_item_data( $instance ) {
        if ( $instance->getType() !== $this->type ) {
            return;
        }

        // Set Display Count as Extra Option.
        $post_meta                      = $this->post_metas['display_count'];
        $extra_options                  = $instance->getExtraOptions();
        $extra_options['display_count'] = get_post_meta( $instance->getID(), $post_meta['meta_key'], true );
        $extra_options['display_count'] = ( $extra_options['display_count'] && is_numeric( $extra_options['display_count'] ) ) ? $extra_options['display_count'] : $post_meta['default'];
        $instance->setExtraOptions( $extra_options );

        // Set post recommendation popup.
        $modal = new FABModal( $instance->getID() );
        $instance->setModal( $modal );

        // Set content.
        $content  = $instance->getRawContent();
        $content .= sprintf( '[fab_related_post display_count="%s"]', $extra_options['display_count'] );
        $instance->setRawContent( $content );

        // Display only on single post of type 'post'.
        if ( ! is_single() || get_post_type() !== 'post' ) {
            $instance->setToBeDisplayed( false );
            return;
        }

        // Get current post ID and related terms.
        $current_post_id = get_the_ID();
        $category_ids    = wp_get_post_categories( $current_post_id );
        $tag_ids         = wp_get_post_tags( $current_post_id, array( 'fields' => 'ids' ) );

        // No terms = nothing to recommend.
        if ( empty( $category_ids ) && empty( $tag_ids ) ) {
            $instance->setToBeDisplayed( false );
            return;
        }

        // Query related posts to see if there's at least one other post to show.
        $related_query = new \WP_Query(
            array(
                'post_type'      => 'post',
                'post_status'    => 'publish',
                'posts_per_page' => 1,
                'post__not_in'   => array( $current_post_id ),
                'tax_query'      => array(
                    'relation' => 'OR',
                    ! empty( $category_ids ) ? array(
                        'taxonomy' => 'category',
                        'field'    => 'term_id',
                        'terms'    => $category_ids,
                    ) : null,
                    ! empty( $tag_ids ) ? array(
                        'taxonomy' => 'post_tag',
                        'field'    => 'term_id',
                        'terms'    => $tag_ids,
                    ) : null,
                ),
            )
        );

        // Clean up null values in tax_query.
        $related_query->query_vars['tax_query'] = array_filter( $related_query->query_vars['tax_query'] );

        if ( ! $related_query->have_posts() ) {
            $instance->setToBeDisplayed( false );
            return;
        }
    }

    /**
     * Add render function.
     *
     * @param object $instance FAB item instance.
     * @return void
     */
    public function add_fab_item_render( $instance ) {
        if ( $instance->getType() !== $this->type ) {
            return;
        }

        $instance->render_content();
    }

    /**
     * Add post recommendations.
     *
     * @param array $related_posts Post recommendations.
     * @param array $atts    Shortcode attributes.
     * @return array
     */
    public static function add_fab_list_of_related_posts( $related_posts, $atts = array() ) {
        // Set default attributes.
        $atts = array_merge(
            array(
                'title' => '',
                'url'   => '',
            ),
            $atts
        );

        $display_count = intval( $atts['display_count'] );

        // Get current post ID and related taxonomies (categories & tags).
        $current_post_id = get_the_ID();

        if ( ! $current_post_id || ! is_single() || get_post_type( $current_post_id ) !== 'post' ) {
            return $related_posts; // Don't do anything if not a valid post.
        }

        // Get category and tag IDs.
        $category_ids = wp_get_post_categories( $current_post_id );
        $tag_ids      = wp_get_post_tags( $current_post_id, array( 'fields' => 'ids' ) );

        if ( empty( $category_ids ) && empty( $tag_ids ) ) {
            return $related_posts; // No terms to base recommendation on.
        }

        // Build the query args.
        $query_args = array(
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'posts_per_page' => $display_count,
            'orderby'        => 'date',
            'order'          => 'DESC',
            'post__not_in'   => array( $current_post_id ), // Exclude current post.
            'tax_query'      => array(
                'relation' => 'OR',
            ),
        );

        if ( ! empty( $category_ids ) ) {
            $query_args['tax_query'][] = array(
                'taxonomy' => 'category',
                'field'    => 'term_id',
                'terms'    => $category_ids,
            );
        }

        if ( ! empty( $tag_ids ) ) {
            $query_args['tax_query'][] = array(
                'taxonomy' => 'post_tag',
                'field'    => 'term_id',
                'terms'    => $tag_ids,
            );
        }

        // Query related posts.
        $query = new \WP_Query( $query_args );

        if ( $query->have_posts() ) {
            while ( $query->have_posts() ) {
                $query->the_post();

                $related_posts[] = array(
                    'title' => get_the_title(),
                    'url'   => get_permalink(),
                );
            }
            wp_reset_postdata();
        }

        return $related_posts;
    }

    /*
    |--------------------------------------------------------------------------
    | Fulfill implemented interface contracts
    |--------------------------------------------------------------------------
     */

    /**
     * JIT Method.
     *
     * @return void
     */
    public static function jit() {
        // Adjust item data.
        add_action( 'fab_item_data', array( __CLASS__, 'jit_add_fab_item_data' ), 10, 1 );

        // Add render function.
        add_action( 'fab_item_render', array( __CLASS__, 'jit_add_fab_item_render' ), 10, 1 );

        // Add post recommendations.
        add_filter( 'fab_list_of_related_posts', array( __CLASS__, 'jit_add_fab_list_of_related_posts' ), 10, 2 );
    }
}
