<?php
/**
 * Exclusions page view. A dedicated sub-menu (scan-scope, not a result), with a
 * Manual Exclusions tab (free; the engine's manual exclusion store) and an
 * Exclusion Rules tab (premium; the shared rule builder, shown as an upsell promo
 * on the free build). Mirrors LIHA's Exclusions page and the shared contract in
 * `../link-image-health-audit/docs/DESIGN-exclusion-rules.md`.
 *
 * The premium rule component (when present) subscribes to the three
 * ssaa_exclusions_* seams below to relabel the tab, clear the promo accent, and
 * render the builder in place of the promo.
 *
 * @package search-social-appearance-audit
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

function ssaa_render_exclusions_page() {
	$base = admin_url( 'admin.php?page=ssaa-exclusions' );

	/**
	 * Exclusions sub-page tabs (slug => label). Free registers 'manual' + a
	 * promo 'rules'; the premium rule layer relabels 'rules' to drop "(Premium)".
	 */
	$tabs = (array) apply_filters( 'ssaa_exclusions_tabs', array(
		'manual' => __( 'Manual Exclusions', 'search-social-appearance-audit' ),
		'rules'  => __( 'Exclusion Rules (Premium)', 'search-social-appearance-audit' ),
	) );

	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only view state.
	$active = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'manual';
	$active = isset( $tabs[ $active ] ) ? $active : 'manual';

	/**
	 * Which tabs are the upsell/promo tabs (star + blue accent). The premium rule
	 * layer clears 'rules' from this when active, so the real builder tab is plain.
	 */
	$promo_tabs = (array) apply_filters( 'ssaa_exclusions_promo_tabs', array( 'rules' ) );

	echo '<div class="wrap ssaa-wrap">';
	SSAA_Plugin::render_page_header( __( 'Exclusions', 'search-social-appearance-audit' ), 'exclusions' );

	// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only flag from our own redirect.
	if ( isset( $_GET['ssaa_reincluded'] ) ) {
		echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Item re-included. It reappears after the next scan.', 'search-social-appearance-audit' ) . '</p></div>';
	}

	echo '<nav class="nav-tab-wrapper ssaa-nav-tab-wrapper">';
	foreach ( $tabs as $key => $label ) {
		$class = 'nav-tab' . ( $active === $key ? ' nav-tab-active' : '' );
		$url   = ( 'manual' === $key ) ? $base : add_query_arg( 'tab', $key, $base );
		if ( in_array( $key, $promo_tabs, true ) ) {
			$class .= ' ssaa-nav-tab-premium';
			echo '<a class="' . esc_attr( $class ) . '" href="' . esc_url( $url ) . '">'
				. '<span class="dashicons dashicons-star-filled ssaa-nav-tab-premium-icon" aria-hidden="true"></span>'
				. esc_html( $label ) . '</a>';
			continue;
		}
		echo '<a class="' . esc_attr( $class ) . '" href="' . esc_url( $url ) . '">' . esc_html( $label ) . '</a>';
	}
	SSAA_Plugin::render_docs_link( 'exclusions' );
	echo '</nav>';

	if ( 'manual' === $active ) {
		ssaa_render_manual_exclusions_tab();
	} elseif ( 'rules' === $active ) {
		/**
		 * Exclusion Rules tab body. The premium rule layer returns its builder
		 * markup (pre-escaped); '' (free build, no subscriber) shows the promo.
		 */
		$body = (string) apply_filters( 'ssaa_exclusions_rules_tab_body', '' );
		if ( '' !== $body ) {
			echo $body; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- premium component returns pre-escaped markup.
		} else {
			ssaa_render_exclusion_rules_promo();
		}
	} else {
		/** Any other registered tab body. No subscribers in the free build. */
		do_action( 'ssaa_exclusions_render_tab', $active );
	}

	SSAA_Plugin::render_admin_footer();
	echo '</div>';
}

/**
 * Manual Exclusions tab (free): the engine's manually-excluded items, each with a
 * Re-include link. Reads stored() - the raw manual set - NOT all(), so a premium
 * rule layer's computed exclusions never appear in the manual list.
 */
function ssaa_render_manual_exclusions_tab() {
	echo '<p class="description">' . esc_html__( 'Items you have manually excluded from the audit. Use the "Appearance audit: Exclude" bulk action on the Posts or Pages list, or the Exclude row action in Results, to add to this list.', 'search-social-appearance-audit' ) . '</p>';

	$refs = SSAA_Engine_Exclusions::stored();
	if ( empty( $refs ) ) {
		echo '<p>' . esc_html__( 'Nothing is excluded yet.', 'search-social-appearance-audit' ) . '</p>';
		return;
	}

	echo '<table class="widefat striped"><thead><tr><th>' . esc_html__( 'Excluded item', 'search-social-appearance-audit' ) . '</th><th></th></tr></thead><tbody>';
	foreach ( $refs as $ref ) {
		$url = wp_nonce_url(
			add_query_arg(
				array( 'page' => 'ssaa-exclusions', 'ssaa_action' => 'reinclude', 'ref' => rawurlencode( $ref ) ),
				admin_url( 'admin.php' )
			),
			'ssaa_reinclude_' . $ref
		);
		echo '<tr><td>' . esc_html( ssaa_exclusion_ref_label( $ref ) ) . '</td>';
		echo '<td><a class="button button-small" href="' . esc_url( $url ) . '">' . esc_html__( 'Re-include', 'search-social-appearance-audit' ) . '</a></td></tr>';
	}
	echo '</tbody></table>';
}

/**
 * Human label for an exclusion ref. 'post:ID' resolves to the post title;
 * 'url:{sha1}' (an excluded archive page) resolves against the LIVE
 * synthesized descriptor set - "{label} - {url}" - so no label storage is
 * needed. A ref that no longer synthesizes (term deleted, archives setting
 * off) falls back to the raw form, which still re-includes correctly.
 *
 * @param string $ref Engine ref.
 * @return string
 */
function ssaa_exclusion_ref_label( $ref ) {
	if ( 0 === strpos( $ref, 'post:' ) ) {
		$id    = (int) substr( $ref, 5 );
		$title = $id > 0 ? get_the_title( $id ) : '';
		return ( '' !== $title ? $title : __( '(untitled)', 'search-social-appearance-audit' ) ) . ' (#' . $id . ')';
	}

	if ( 0 === strpos( $ref, 'url:' ) ) {
		static $synthesized = null;
		if ( null === $synthesized ) {
			$synthesized = array();
			// Bypass the scan_archives gate: an excluded archive must stay
			// labelled even while the setting is off, so index the raw
			// synthesized set, not the gated one. The Site row (AI access,
			// 1.2.0) is indexed too - it is url-kind and excludable like any
			// other row.
			foreach ( array_merge( (array) SSAA_Discovery::synthesized_raw(), (array) SSAA_Discovery::site_descriptor() ) as $descriptor ) {
				if ( isset( $descriptor['ref'] ) ) {
					$synthesized[ (string) $descriptor['ref'] ] = $descriptor;
				}
			}
		}
		if ( isset( $synthesized[ $ref ] ) ) {
			return (string) $synthesized[ $ref ]['label'] . ' - ' . (string) $synthesized[ $ref ]['permalink'];
		}
	}

	return $ref;
}

/**
 * Exclusion Rules tab - upsell promo (free build). Description only, reusing SSAA's
 * Premium-tab vocabulary (.ssaa-premium-*). No locked/disabled UI, no mock builder
 * (DESIGN s.11 + WP.org Guideline 5). Replaced by the real builder when the premium
 * rule layer is present.
 */
function ssaa_render_exclusion_rules_promo() {
	$upgrade_url = SSAA_License::upgrade_url();
	$compare_url = SSAA_Plugin::docs_url( 'features/premium-features', 'exclusions_promo' );

	echo '<div class="ssaa-premium-tab">';
	echo '<p class="ssaa-premium-intro">' . esc_html__( 'Exclusion Rules keep matching content out of every audit automatically, on top of the manual exclusions you set by hand.', 'search-social-appearance-audit' ) . '</p>';

	echo '<p class="ssaa-premium-cta">';
	if ( '' !== $upgrade_url ) {
		echo '<a class="button button-primary" href="' . esc_url( $upgrade_url ) . '">'
			. esc_html__( 'Upgrade to Premium', 'search-social-appearance-audit' ) . '</a> ';
	}
	echo '<a href="' . esc_url( $compare_url ) . '" target="_blank" rel="noopener">'
		. esc_html__( 'See the full plan comparison', 'search-social-appearance-audit' ) . '</a>';
	echo '</p>';

	echo '<div class="ssaa-premium-groups"><div class="ssaa-premium-group">';
	echo '<h3>' . esc_html__( 'Exclude by rule', 'search-social-appearance-audit' ) . '</h3><ul>';
	echo '<li>' . esc_html__( 'Set conditions like a URL pattern, post type, category, tag or author. Anything that matches is skipped automatically on every audit.', 'search-social-appearance-audit' ) . '</li>';
	echo '<li>' . esc_html__( 'New content that matches a rule is excluded the moment it is published.', 'search-social-appearance-audit' ) . '</li>';
	echo '<li>' . esc_html__( 'Save a set of rules and apply the same standard across all the sites you manage.', 'search-social-appearance-audit' ) . '</li>';
	echo '</ul></div></div>';

	echo '</div>';
}

ssaa_render_exclusions_page();
