<?php
/**
 * GSC Monitor Page.
 *
 * Tools → SEO Monitor: a time-series view of whether the SEO work is
 * recovering traffic. Shows the site-wide clicks/impressions/position trend
 * since monitoring began, plus a watchlist of specific pages (e.g. the
 * Phase-1 targets) with their own trend lines. History accrues from the day
 * the module is enabled — that's expected and stated on the page.
 *
 * Watchlist add/remove is a plain form POST (no JS) handled at render time.
 *
 * @package Platform\Helm\Modules\GSC
 */

declare( strict_types = 1 );

namespace Platform\Helm\Modules\GSC;

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

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

final class GscMonitorPage {

	public const PAGE_SLUG   = 'platform-helm-monitor';
	public const PARENT_SLUG = 'platform-helm';
	private const NONCE       = 'platform_helm_monitor';

	public function __construct(
		private Assets $assets,
		private GscSnapshotStore $snapshots
	) {}

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

	public function register_menu(): void {
		if ( ! Authorization::is_master_admin() ) {
			return;
		}
		$hook = add_submenu_page(
			self::PARENT_SLUG,
			__( 'SEO Monitor', 'platform-helm' ),
			__( 'SEO Monitor', '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();
	}

	private function handle_post(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		if ( empty( $_POST['topla_monitor_action'] ) ) {
			return;
		}
		if ( ! Authorization::is_master_admin() ) {
			return;
		}
		check_admin_referer( self::NONCE );
		$action = sanitize_text_field( wp_unslash( $_POST['topla_monitor_action'] ) );

		if ( 'add' === $action && isset( $_POST['topla_monitor_target'] ) ) {
			$raw = trim( sanitize_text_field( wp_unslash( $_POST['topla_monitor_target'] ) ) );
			$pid = ctype_digit( $raw ) ? (int) $raw : (int) url_to_postid( $raw );
			if ( $pid > 0 ) {
				$this->snapshots->add_to_watchlist( $pid );
			}
		} elseif ( 'remove' === $action && isset( $_POST['topla_monitor_pid'] ) ) {
			$this->snapshots->remove_from_watchlist( (int) $_POST['topla_monitor_pid'] );
		}
	}

	/**
	 * Tiny inline SVG sparkline from a series of numbers.
	 *
	 * @param array<int,float> $values
	 */
	private function sparkline( array $values, string $stroke = '#2271b1' ): string {
		$values = array_values( array_map( 'floatval', $values ) );
		$n      = count( $values );
		if ( $n < 2 ) {
			return '<span style="color:#a7aaad;">' . esc_html__( 'not enough data yet', 'platform-helm' ) . '</span>';
		}
		$w   = 160;
		$h   = 32;
		$min = min( $values );
		$max = max( $values );
		$rng = ( $max - $min ) ?: 1.0;
		$pts = [];
		foreach ( $values as $i => $v ) {
			$x     = round( ( $i / ( $n - 1 ) ) * $w, 1 );
			$y     = round( $h - ( ( $v - $min ) / $rng ) * $h, 1 );
			$pts[] = $x . ',' . $y;
		}
		$points = implode( ' ', $pts );
		return '<svg width="' . $w . '" height="' . $h . '" viewBox="0 0 ' . $w . ' ' . $h . '" preserveAspectRatio="none" style="vertical-align:middle;">'
			. '<polyline fill="none" stroke="' . esc_attr( $stroke ) . '" stroke-width="2" points="' . esc_attr( $points ) . '" /></svg>';
	}

	public function render(): void {
		Authorization::require_master_admin();
		$this->handle_post();

		$site      = $this->snapshots->history( 0, 180 );
		$watchlist = $this->snapshots->watchlist();
		?>
		<div class="wrap ph-gsc">
			<h1><?php esc_html_e( 'SEO Monitor', 'platform-helm' ); ?></h1>
			<p class="ph-gsc-lead">
				<?php esc_html_e( 'Tracks whether traffic is recovering over time. A snapshot is recorded each day the daily sync runs, so the trend builds up from the day you enabled this — give it a few weeks to become meaningful.', 'platform-helm' ); ?>
			</p>

			<div class="ph-gsc-card">
				<h2><?php esc_html_e( 'Site-wide trend', 'platform-helm' ); ?></h2>
				<?php if ( count( $site ) < 2 ) : ?>
					<p><?php esc_html_e( 'Only one snapshot so far (or none). Run a sync daily and this trend will fill in. Each daily sync adds one point.', 'platform-helm' ); ?></p>
				<?php else : ?>
					<?php
					$clicks = array_map( static fn( $r ) => (float) $r['clicks'], $site );
					$impr   = array_map( static fn( $r ) => (float) $r['impressions'], $site );
					$first  = $site[0];
					$last   = $site[ count( $site ) - 1 ];
					$dc     = (int) $last['clicks'] - (int) $first['clicks'];
					?>
					<table class="widefat striped ph-gsc-table">
						<thead><tr>
							<th><?php esc_html_e( 'Metric', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Trend', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'First', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Latest', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Change', 'platform-helm' ); ?></th>
						</tr></thead>
						<tbody>
							<tr>
								<td><strong><?php esc_html_e( 'Clicks', 'platform-helm' ); ?></strong></td>
								<td><?php echo $this->sparkline( $clicks, '#2271b1' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
								<td><?php echo esc_html( number_format_i18n( (int) $first['clicks'] ) ); ?></td>
								<td><?php echo esc_html( number_format_i18n( (int) $last['clicks'] ) ); ?></td>
								<td style="color:<?php echo $dc >= 0 ? '#1a7f37' : '#b32d2e'; ?>;"><?php echo esc_html( ( $dc >= 0 ? '+' : '' ) . number_format_i18n( $dc ) ); ?></td>
							</tr>
							<tr>
								<td><strong><?php esc_html_e( 'Impressions', 'platform-helm' ); ?></strong></td>
								<td><?php echo $this->sparkline( $impr, '#8c6d1f' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
								<td><?php echo esc_html( number_format_i18n( (int) $first['impressions'] ) ); ?></td>
								<td><?php echo esc_html( number_format_i18n( (int) $last['impressions'] ) ); ?></td>
								<td><?php echo esc_html( ( ( (int) $last['impressions'] - (int) $first['impressions'] ) >= 0 ? '+' : '' ) . number_format_i18n( (int) $last['impressions'] - (int) $first['impressions'] ) ); ?></td>
							</tr>
							<tr>
								<td><strong><?php esc_html_e( 'Avg. position', 'platform-helm' ); ?></strong></td>
								<td>&mdash;</td>
								<td><?php echo esc_html( number_format( (float) $first['position'], 1 ) ); ?></td>
								<td><?php echo esc_html( number_format( (float) $last['position'], 1 ) ); ?></td>
								<td><?php esc_html_e( 'lower is better', 'platform-helm' ); ?></td>
							</tr>
						</tbody>
					</table>
					<p class="ph-gsc-hint">
						<?php
						echo esc_html( sprintf(
							/* translators: 1: first date, 2: last date, 3: point count */
							__( 'Showing %3$d daily snapshots from %1$s to %2$s.', 'platform-helm' ),
							(string) $first['snap_date'],
							(string) $last['snap_date'],
							count( $site )
						) );
						?>
					</p>
				<?php endif; ?>
			</div>

			<div class="ph-gsc-card">
				<h2><?php esc_html_e( 'Watched pages', 'platform-helm' ); ?></h2>
				<p class="ph-gsc-hint"><?php esc_html_e( 'Add the pages you are actively working on (e.g. the Phase-1 targets) to track each one toward its goal position. Paste a URL or a post ID.', 'platform-helm' ); ?></p>

				<form method="post" class="ph-gsc-row" style="margin:8px 0 14px;">
					<?php wp_nonce_field( self::NONCE ); ?>
					<input type="hidden" name="topla_monitor_action" value="add" />
					<input type="text" name="topla_monitor_target" class="regular-text" placeholder="<?php esc_attr_e( 'https://example.com/…  or  1234', 'platform-helm' ); ?>" />
					<button type="submit" class="button button-primary"><?php esc_html_e( 'Add to watchlist', 'platform-helm' ); ?></button>
				</form>

				<?php if ( empty( $watchlist ) ) : ?>
					<p><?php esc_html_e( 'No pages watched yet.', 'platform-helm' ); ?></p>
				<?php else : ?>
					<table class="widefat striped ph-gsc-table">
						<thead><tr>
							<th><?php esc_html_e( 'Page', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Clicks trend', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Latest pos.', 'platform-helm' ); ?></th>
							<th><?php esc_html_e( 'Latest clicks', 'platform-helm' ); ?></th>
							<th></th>
						</tr></thead>
						<tbody>
							<?php foreach ( $watchlist as $pid ) : ?>
								<?php
								$h    = $this->snapshots->history( (int) $pid, 180 );
								$cl   = array_map( static fn( $r ) => (float) $r['clicks'], $h );
								$lastp = ! empty( $h ) ? $h[ count( $h ) - 1 ] : null;
								?>
								<tr>
									<td>
										<a href="<?php echo esc_url( (string) get_edit_post_link( (int) $pid ) ); ?>"><?php echo esc_html( get_the_title( (int) $pid ) ?: ( '#' . (int) $pid ) ); ?></a>
									</td>
									<td><?php echo $this->sparkline( $cl, '#2271b1' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
									<td><?php echo $lastp ? esc_html( number_format( (float) $lastp['position'], 1 ) ) : '&mdash;'; ?></td>
									<td><?php echo $lastp ? esc_html( number_format_i18n( (int) $lastp['clicks'] ) ) : '&mdash;'; ?></td>
									<td>
										<form method="post" style="margin:0;">
											<?php wp_nonce_field( self::NONCE ); ?>
											<input type="hidden" name="topla_monitor_action" value="remove" />
											<input type="hidden" name="topla_monitor_pid" value="<?php echo esc_attr( (string) (int) $pid ); ?>" />
											<button type="submit" class="button button-small button-link-delete"><?php esc_html_e( 'Remove', 'platform-helm' ); ?></button>
										</form>
									</td>
								</tr>
							<?php endforeach; ?>
						</tbody>
					</table>
				<?php endif; ?>
			</div>
		</div>
		<?php
	}
}
