<?php

defined( 'ABSPATH' ) || exit;

/**
 * Analytics module — Google Tag Manager + Google Search Console verification.
 *
 * Drops the GTM head script + body noscript iframe into every frontend page
 * (gated by an in-module toggle so existing client sites don't auto-emit
 * tracking on update), and the Search Console verification meta tag into
 * <head> when a token is configured.
 *
 * The Search Console field is paste-tolerant: the admin can paste the full
 * <meta ...> tag, just the verification token, or a verification-file URL —
 * the sanitizer extracts the bare ID either way.
 *
 * Group: `frontend` (alongside Favicon, Menu Visibility — modules that
 * inject markup on the public-facing site).
 *
 * @package BW_Dev
 */
class BW_Dev_Module_Analytics implements BW_Dev_Module_Interface {

	public function slug(): string {
		return 'analytics';
	}

	public function label(): string {
		return __( 'Analytics', 'bw-dev' );
	}

	public function group(): string {
		return 'frontend';
	}

	public function default_settings(): array {
		return array(
			// GTM emission is keyed off `gtm_id`: non-empty -> emit, empty -> skip.
			// No separate toggle. To pause GTM, clear the ID (or disable the
			// whole Analytics module on the Modules tab).
			'gtm_id'            => '',
			'search_console_id' => '',
		);
	}

	public function sanitize( array $data ): array {
		$out = $this->default_settings();

		$raw_gtm       = isset( $data['gtm_id'] ) ? trim( wp_unslash( (string) $data['gtm_id'] ) ) : '';
		$out['gtm_id'] = (string) preg_replace( '/[^A-Za-z0-9_-]/', '', $raw_gtm );

		$raw_sc                   = isset( $data['search_console_id'] ) ? wp_unslash( (string) $data['search_console_id'] ) : '';
		$out['search_console_id'] = $this->extract_search_console_id( (string) $raw_sc );

		return $out;
	}

	public function register(): void {
		add_action( 'wp_head',       array( $this, 'output_head' ), 1 );
		add_action( 'wp_body_open',  array( $this, 'output_body' ), 1 );
	}

	public function uninstall(): void {
		// Root option drop in uninstall.php handles persisted state.
	}

	// -------------------------------------------------------------------
	// Frontend output
	// -------------------------------------------------------------------

	public function output_head(): void {
		$settings = $this->get_settings();
		$gtm      = (string) $settings['gtm_id'];

		if ( '' !== $gtm ) {
			echo "\n<!-- Google Tag Manager -->\n";
			echo "<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\n";
			echo "new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\n";
			echo "j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\n";
			echo "'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\n";
			echo "})(window,document,'script','dataLayer','" . esc_js( $gtm ) . "');</script>\n";
			echo "<!-- End Google Tag Manager -->\n";
		}

		if ( '' !== (string) $settings['search_console_id'] ) {
			printf(
				'<meta name="google-site-verification" content="%s" />' . "\n",
				esc_attr( (string) $settings['search_console_id'] )
			);
		}
	}

	public function output_body(): void {
		$settings = $this->get_settings();
		$gtm      = (string) $settings['gtm_id'];
		if ( '' === $gtm ) {
			return;
		}
		echo "\n<!-- Google Tag Manager (noscript) -->\n";
		echo '<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=' . esc_attr( $gtm ) . '"' . "\n";
		echo 'height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>' . "\n";
		echo "<!-- End Google Tag Manager (noscript) -->\n";
	}

	// -------------------------------------------------------------------
	// Helpers
	// -------------------------------------------------------------------

	private function get_settings(): array {
		$saved = (array) bw_dev()->settings()->get( $this->slug(), null, array() );
		return wp_parse_args( $saved, $this->default_settings() );
	}

	/**
	 * Tolerant Search Console token extractor. Accepts:
	 *   - the full <meta name="google-site-verification" content="..." /> tag
	 *   - just the bare verification token
	 *   - a verification-file URL or filename (e.g. "google1234abcd.html")
	 *
	 * Returns the cleanest possible token, stripped of unsafe characters.
	 */
	private function extract_search_console_id( string $raw ): string {
		$raw = trim( $raw );
		if ( '' === $raw ) {
			return '';
		}
		// 1. Full meta tag (single or double quotes).
		if ( preg_match( '/content\s*=\s*["\']([^"\']+)["\']/i', $raw, $m ) ) {
			return (string) preg_replace( '/[^A-Za-z0-9_=\\-]/', '', $m[1] );
		}
		// 2. URL or bare filename ending in .html — the verification-file
		//    method. Strip any path + extension, leave the base name.
		$leaf = basename( $raw );
		if ( preg_match( '/^([A-Za-z0-9_=\\-]+)\.html?$/i', $leaf, $m ) ) {
			return $m[1];
		}
		// 3. Raw token — sanitize down to the allowed char set.
		return (string) preg_replace( '/[^A-Za-z0-9_=\\-]/', '', $raw );
	}

	// -------------------------------------------------------------------
	// Settings tab
	// -------------------------------------------------------------------

	public function render_tab(): void {
		$settings    = $this->get_settings();
		$name_prefix = BW_Dev_Settings::OPTION . '[' . $this->slug() . ']';
		?>
		<p class="description">
			<?php esc_html_e( 'Drops Google Tag Manager script tags and the Search Console verification meta tag into every frontend page. Each is keyed off its own field below — leave a field blank to skip that feature. Nothing is emitted on admin, login, or REST responses.', 'bw-dev' ); ?>
		</p>

		<h2><?php esc_html_e( 'Google Tag Manager', 'bw-dev' ); ?></h2>
		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row"><label for="bw-dev-analytics-gtm-id"><?php esc_html_e( 'GTM ID', 'bw-dev' ); ?></label></th>
					<td>
						<input type="text"
							id="bw-dev-analytics-gtm-id"
							name="<?php echo esc_attr( $name_prefix . '[gtm_id]' ); ?>"
							value="<?php echo esc_attr( $settings['gtm_id'] ); ?>"
							class="regular-text code"
							placeholder="GTM-XXXXXXX" />
						<p class="description">
							<?php esc_html_e( 'Container ID from Google Tag Manager (Admin → Container Settings). Format is GTM- followed by alphanumerics. Leave blank to skip — no GTM markup is emitted when this is empty.', 'bw-dev' ); ?>
						</p>
					</td>
				</tr>
			</tbody>
		</table>

		<h2 style="margin-top:30px;"><?php esc_html_e( 'Google Search Console', 'bw-dev' ); ?></h2>
		<table class="form-table" role="presentation">
			<tbody>
				<tr>
					<th scope="row"><label for="bw-dev-analytics-sc-id"><?php esc_html_e( 'Verification token', 'bw-dev' ); ?></label></th>
					<td>
						<input type="text"
							id="bw-dev-analytics-sc-id"
							name="<?php echo esc_attr( $name_prefix . '[search_console_id]' ); ?>"
							value="<?php echo esc_attr( $settings['search_console_id'] ); ?>"
							class="large-text code"
							placeholder='<meta name="google-site-verification" content="..." />' />
						<p class="description">
							<?php esc_html_e( 'Paste the full HTML meta tag from Search Console (we extract the content="…" value), the verification-file URL (we extract the file name), or just the bare token. Leave blank to skip — no meta tag is emitted when this is empty.', 'bw-dev' ); ?>
						</p>
						<?php if ( '' !== $settings['search_console_id'] ) : ?>
							<p style="margin-top:6px;">
								<?php esc_html_e( 'Stored as:', 'bw-dev' ); ?>
								<code><?php echo esc_html( $settings['search_console_id'] ); ?></code>
							</p>
							<p style="margin-top:4px;">
								<?php esc_html_e( 'Will emit:', 'bw-dev' ); ?>
								<code>&lt;meta name="google-site-verification" content="<?php echo esc_html( $settings['search_console_id'] ); ?>" /&gt;</code>
							</p>
						<?php endif; ?>
					</td>
				</tr>
			</tbody>
		</table>
		<?php
	}
}
