<?php
/**
 * LinkCentral Most Popular Links Class
 *
 * This class handles the functionality for retrieving and displaying
 * the most popular (most clicked) links.
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class LinkCentral_Most_Popular_Links {

	/**
	 * The main admin object.
	 *
	 * @var LinkCentral_Admin
	 */
	private $admin;

	/**
	 * Constructor.
	 *
	 * @param LinkCentral_Admin $admin The main admin object.
	 */
	public function __construct( $admin ) {
		$this->admin = $admin;
	}

	/**
	 * Retrieve top links data for the given filter context.
	 *
	 * @param LinkCentral_Insights_Filters $filters  Filter context.
	 * @param int                          $page     Page number.
	 * @param int                          $per_page Items per page.
	 * @return array
	 */
	public function get_top_links_data( LinkCentral_Insights_Filters $filters, $page, $per_page ) {
		global $wpdb;

		$category_id = $filters->category_id;

		$category_link_ids = array();
		if ( $category_id ) {
			$category_link_ids = LinkCentral_Insights_Query_Builder::get_category_link_ids( $category_id );
			if ( empty( $category_link_ids ) ) {
				return $this->empty_top_links_response( $page, $per_page );
			}
		}

		$clauses = array();
		$params  = array();
		if ( ! LinkCentral_Insights_Query_Builder::append_stats_filters( $filters, $clauses, $params ) ) {
			return $this->empty_top_links_response( $page, $per_page );
		}

		$query = "SELECT s.link_id,
				COUNT(*) as total_clicks,
				SUM(s.first_click) as unique_clicks
			FROM {$wpdb->prefix}linkcentral_stats s
			WHERE " . implode( ' AND ', $clauses ) . '
			GROUP BY s.link_id ORDER BY total_clicks DESC';

		$rows = LinkCentral_Insights_Query_Builder::query( $query, $params );

		$click_counts = array();
		foreach ( $rows as $row ) {
			$click_counts[ (int) $row['link_id'] ] = (object) array(
				'total_clicks'  => (int) $row['total_clicks'],
				'unique_clicks' => (int) $row['unique_clicks'],
			);
		}

		$paged_link_ids = array_slice( array_keys( $click_counts ), ( $page - 1 ) * $per_page, $per_page );

		$query = new WP_Query(
			array(
				'post_type'      => 'linkcentral_link',
				'posts_per_page' => -1,
				'post_status'    => array( 'publish', 'draft', 'private', 'trash' ),
				'post__in'       => $paged_link_ids,
				'orderby'        => 'post__in',
			)
		);

		$processed_results = array();
		$all_link_ids        = array_keys( $click_counts );
		foreach ( $paged_link_ids as $current_link_id ) {
			$post        = $this->find_post_by_id( $query->posts, $current_link_id );
			$global_rank = array_search( $current_link_id, $all_link_ids, true ) + 1;

			if ( $post ) {
				$dynamic_rules = get_post_meta( $post->ID, '_linkcentral_dynamic_rules', true );
				$is_premium    = function_exists( 'linkcentral_fs' ) && linkcentral_fs()->can_use_premium_code__premium_only();

				$processed_results[] = (object) array(
					'ID'                        => $post->ID,
					'post_title'                => $post->post_title,
					'post_status'               => $post->post_status,
					'slug'                      => $post->post_name,
					'total_clicks'              => $click_counts[ $post->ID ]->total_clicks,
					'unique_clicks'             => $click_counts[ $post->ID ]->unique_clicks,
					'destination_url'           => get_post_meta( $post->ID, '_linkcentral_destination_url', true ),
					'destination_url_truncated' => linkcentral_truncate_url( get_post_meta( $post->ID, '_linkcentral_destination_url', true ) ),
					'is_deleted'                => false,
					'is_trashed'                => ( 'trash' === $post->post_status ),
					'is_draft'                  => ( 'draft' === $post->post_status ),
					'is_private'                => ( 'private' === $post->post_status ),
					'edit_link'                 => get_edit_post_link( $post->ID, 'raw' ),
					'has_dynamic_rules'         => $is_premium && ! empty( $dynamic_rules ),
					'rank'                      => $global_rank,
				);
			} else {
				$processed_results[] = (object) array(
					'ID'                        => $current_link_id,
					'post_title'                => 'Deleted Link',
					'post_status'               => 'deleted',
					'slug'                      => '',
					'total_clicks'              => $click_counts[ $current_link_id ]->total_clicks,
					'unique_clicks'             => $click_counts[ $current_link_id ]->unique_clicks,
					'destination_url'           => '',
					'destination_url_truncated' => linkcentral_truncate_url( '' ),
					'is_deleted'                => true,
					'is_trashed'                => false,
					'is_draft'                  => false,
					'is_private'                => false,
					'edit_link'                 => '',
					'rank'                      => $global_rank,
				);
			}
		}

		$total_items = count( $click_counts );
		$total_pages = (int) ceil( $total_items / $per_page );

		return array(
			'links'          => $processed_results,
			'current_page'   => $page,
			'total_pages'    => $total_pages,
			'total_items'    => $total_items,
			'items_per_page' => $per_page,
		);
	}

	/**
	 * @param int $page     Page number.
	 * @param int $per_page Per page.
	 * @return array
	 */
	private function empty_top_links_response( $page, $per_page ) {
		return array(
			'links'          => array(),
			'current_page'   => $page,
			'total_pages'    => 1,
			'total_items'    => 0,
			'items_per_page' => $per_page,
		);
	}

	/**
	 * Find a post by ID in an array of posts.
	 *
	 * @param array $posts Posts.
	 * @param int   $id    Post ID.
	 * @return WP_Post|null
	 */
	private function find_post_by_id( $posts, $id ) {
		foreach ( $posts as $post ) {
			if ( (int) $post->ID === (int) $id ) {
				return $post;
			}
		}
		return null;
	}
}
