<?php
/**
 * Content Gap Page.
 *
 * Surfaces "opportunity" queries — ones where the site already earns
 * impressions but the best-ranking page is weak — and lets AI cluster them
 * into concrete new-article topics (or expansions of existing ones).
 *
 * @package Platform\Helm\Modules\GSC
 */

declare( strict_types = 1 );

namespace Platform\Helm\Modules\GSC;

use Platform\Helm\Core\Assets;
use Platform\Helm\Core\Authorization;
use Platform\Helm\Core\LlmClient;
use Platform\Helm\Core\LlmSettings;

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

final class GscContentGapPage {

	public const PAGE_SLUG   = 'platform-helm-content-gap';
	public const PARENT_SLUG = 'platform-helm';
	private const NONCE      = 'platform_helm_content_gap';

	public function __construct(
		private Assets $assets,
		private GscQueryStore $query_store
	) {}

	public function register_hooks(): void {
		add_action( 'admin_menu', [ $this, 'register_menu' ], 46 );
		add_action( 'wp_ajax_platform_helm_content_gap', [ $this, 'ajax_suggest' ] );
	}

	public function register_menu(): void {
		if ( ! Authorization::is_master_admin() ) {
			return;
		}
		$hook = add_submenu_page(
			self::PARENT_SLUG,
			__( 'Content Gaps', 'platform-helm' ),
			__( 'Content Gaps', 'platform-helm' ),
			'manage_options',
			self::PAGE_SLUG,
			[ $this, 'render' ]
		);
		if ( $hook ) {
			add_action( 'load-' . $hook, [ $this, 'enqueue' ] );
		}
	}

	public function enqueue(): void {
		$this->assets->enqueue_seo_reports();
	}

	/** @return array<int,array<string,mixed>> */
	private function gaps(): array {
		return $this->query_store->opportunity_queries( 100, 8.0, 40 );
	}

	public function ajax_suggest(): void {
		check_ajax_referer( self::NONCE, 'nonce' );
		Authorization::require_master_admin_ajax();

		$gaps = $this->gaps();
		if ( empty( $gaps ) ) {
			wp_send_json_error( [ 'message' => __( 'No opportunity queries found yet. Sync Search Console first.', 'platform-helm' ) ] );
		}

		$lines = '';
		foreach ( $gaps as $g ) {
			$lines .= '- ' . (string) $g['query'] . ' (' . number_format( (int) $g['impressions'] ) . ' impr, best pos ' . number_format( (float) $g['best_position'], 1 ) . ")\n";
		}

		$system = 'You are a content strategist for this website. '
			. 'Below are search queries the site already gets impressions for but ranks poorly on — content opportunities. '
			. 'Cluster the related ones and propose a focused content plan. For each idea give: a working TITLE, the SEARCH INTENT, whether to CREATE a new article or EXPAND an existing one, and the 3–5 queries it would target. '
			. 'Prioritise the highest-impression clusters. Keep it tight and practical. Plain text with clear headings per idea. Propose at most 6 ideas.';
		$user = "Opportunity queries (impressions, best position):\n" . $lines;

		$res = LlmClient::chat(
			[
				[ 'role' => 'system', 'content' => $system ],
				[ 'role' => 'user', 'content' => $user ],
			],
			[ 'max_tokens' => 1100, 'temperature' => 0.5 ]
		);
		if ( is_wp_error( $res ) ) {
			wp_send_json_error( [ 'message' => $res->get_error_message() ] );
		}
		wp_send_json_success( [ 'plan' => $res ] );
	}

	public function render(): void {
		Authorization::require_master_admin();
		$gaps  = $this->gaps();
		$ai_on = LlmSettings::is_configured();
		$nonce = wp_create_nonce( self::NONCE );
		?>
		<div class="wrap ph-gsc">
			<h1><?php esc_html_e( 'Content Gaps', 'platform-helm' ); ?></h1>
			<p class="ph-gsc-lead"><?php esc_html_e( 'Queries where Google already shows your site but you rank poorly (best position 8+). These are the topics you are closest to winning — strengthen or create content here for the fastest gains.', 'platform-helm' ); ?></p>

			<?php if ( empty( $gaps ) ) : ?>
				<div class="notice notice-warning inline"><p>
					<?php
					printf(
						/* translators: %s settings URL */
						wp_kses_post( __( 'No opportunity queries yet. Run a sync on <a href="%s">Search Console</a> first.', 'platform-helm' ) ),
						esc_url( admin_url( 'admin.php?page=platform-helm-gsc' ) )
					);
					?>
				</p></div>
			<?php else : ?>

				<?php if ( $ai_on ) : ?>
					<div class="ph-gsc-card">
						<button type="button" class="button button-primary" id="ph-gap-btn"><?php esc_html_e( 'Suggest article topics from these gaps (AI)', 'platform-helm' ); ?></button>
						<span id="ph-gap-msg" class="ph-gsc-hint" aria-live="polite"></span>
						<div id="ph-gap-out" class="ph-ai-out" style="display:none; white-space:pre-wrap; line-height:1.55; background:#fff; border:1px solid #e0e6ee; border-radius:6px; padding:14px; margin-top:10px;"></div>
					</div>
				<?php endif; ?>

				<div class="ph-gsc-card">
					<table class="widefat striped ph-gsc-table">
						<thead><tr>
							<th><?php esc_html_e( 'Query', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Impressions', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Clicks', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Best position', 'platform-helm' ); ?></th>
						</tr></thead>
						<tbody>
							<?php foreach ( $gaps as $g ) : ?>
								<tr>
									<td><?php echo esc_html( (string) $g['query'] ); ?></td>
									<td><?php echo esc_html( number_format_i18n( (int) $g['impressions'] ) ); ?></td>
									<td><?php echo esc_html( number_format_i18n( (int) $g['clicks'] ) ); ?></td>
									<td><?php echo esc_html( number_format( (float) $g['best_position'], 1 ) ); ?></td>
								</tr>
							<?php endforeach; ?>
						</tbody>
					</table>
				</div>

				<?php if ( $ai_on ) : ?>
				<script>
				( function () {
					var url = <?php echo wp_json_encode( admin_url( 'admin-ajax.php' ) ); ?>;
					var nonce = <?php echo wp_json_encode( $nonce ); ?>;
					var btn = document.getElementById( 'ph-gap-btn' );
					var out = document.getElementById( 'ph-gap-out' );
					var msg = document.getElementById( 'ph-gap-msg' );
					if ( ! btn ) { return; }
					btn.addEventListener( 'click', function () {
						btn.disabled = true; var lbl = btn.textContent; btn.textContent = 'Clustering the gaps…';
						out.style.display = ''; out.textContent = 'Thinking…'; if ( msg ) { msg.textContent = ''; }
						var body = new URLSearchParams();
						body.append( 'action', 'platform_helm_content_gap' );
						body.append( 'nonce', nonce );
						fetch( url, { method: 'POST', credentials: 'same-origin', body: body } )
							.then( function ( r ) { return r.json(); } )
							.then( function ( res ) {
								btn.disabled = false; btn.textContent = lbl;
								out.textContent = ( res && res.success && res.data ) ? res.data.plan : ( ( res && res.data && res.data.message ) ? res.data.message : 'Could not generate.' );
							} )
							.catch( function () { btn.disabled = false; btn.textContent = lbl; out.textContent = 'Request failed — try again.'; } );
					} );
				}() );
				</script>
				<?php endif; ?>

			<?php endif; ?>
		</div>
		<?php
	}
}
