<?php
/**
 * MYAIO Robots Meta API
 * REST API endpoints to check robots meta (and X-Robots-Tag) for URLs on this site,
 * and to enable outputting a robots meta tag in <head>.
 *
 * NOTE:
 * - Auth is handled by shared utils: myaio_sac_rest_permission_check()
 * - Options kept as-is to avoid breaking existing installs:
 *     sac_enable_robots_meta
 *     sac_robots_meta_content
 */

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

/**
 * REST routes
 */
add_action(
	'rest_api_init',
	function () {

		register_rest_route(
			'myaio/v1',
			'/check-robots-meta',
			[
				'methods'             => 'GET',
				'callback'            => 'myaio_check_robots_meta',
				'permission_callback' => 'myaio_sac_rest_permission_check',
				'args'                => [
					'url'  => [ 'required' => false, 'type' => 'string' ],
					'path' => [ 'required' => false, 'type' => 'string' ],
					'key'  => [ 'required' => true, 'type' => 'string' ], // validated by shared util
				],
			]
		);

		register_rest_route(
			'myaio/v1',
			'/generate-robots-meta',
			[
				'methods'             => 'POST',
				'callback'            => 'myaio_generate_robots_meta',
				'permission_callback' => 'myaio_sac_rest_permission_check',
				'args'                => [
					'key'     => [ 'required' => true, 'type' => 'string' ], // validated by shared util
					'content' => [ 'required' => false, 'type' => 'string' ],
					'enable'  => [ 'required' => false, 'type' => 'boolean' ],
				],
			]
		);
	}
);

/**
 * Normalize/validate target URL:
 * - Accepts full ?url= OR relative ?path=
 * - Defaults to home_url()
 * - Ensures same host as the WP site (prevents external fetch)
 *
 * @param WP_REST_Request $request Request.
 * @return string|WP_Error
 */
function myaio_get_target_url( WP_REST_Request $request ) {
	$url  = (string) $request->get_param( 'url' );
	$path = (string) $request->get_param( 'path' );

	$url  = trim( $url );
	$path = trim( $path );

	if ( '' !== $path && '' === $url ) {
		// allow "/about" or "about"
		$path = ltrim( $path, '/' );
		$url  = home_url( '/' . $path );
	}

	if ( '' === $url ) {
		$url = home_url( '/' );
	}

	$url = esc_url_raw( $url );

	if ( '' === $url || ! wp_http_validate_url( $url ) ) {
		return new WP_Error( 'invalid_url', 'Invalid URL provided.', [ 'status' => 400 ] );
	}

	// SSRF safety: only allow same host as the WP site.
	$site_host = wp_parse_url( home_url( '/' ), PHP_URL_HOST );
	$url_host  = wp_parse_url( $url, PHP_URL_HOST );

	if ( ! $site_host || ! $url_host || 0 !== strcasecmp( (string) $site_host, (string) $url_host ) ) {
		return new WP_Error( 'forbidden_host', 'Only URLs on this site are allowed.', [ 'status' => 403 ] );
	}

	return $url;
}

/**
 * GET /myaio/v1/check-robots-meta?key=...&url=... OR &path=...
 *
 * Returns:
 * - meta_available (true/false)
 * - content (merged robots directives if found)
 * - x_robots_tag (optional, if present)
 * - http_status
 *
 * @param WP_REST_Request $request Request.
 * @return WP_REST_Response|array|WP_Error
 */
function myaio_check_robots_meta( WP_REST_Request $request ) {

	$target_url = myaio_get_target_url( $request );
	if ( is_wp_error( $target_url ) ) {
		return $target_url;
	}

	$response = wp_remote_get(
		$target_url,
		[
			'timeout'     => 15,
			'redirection' => 5,
			'user-agent'  => 'myaio-robots-check/1.1.0',
			'headers'     => [
				'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
			],
		]
	);

	if ( is_wp_error( $response ) ) {
		return new WP_REST_Response(
			[
				'error'   => 'URL unreachable',
				'details' => $response->get_error_message(),
			],
			500
		);
	}

	$status       = (int) wp_remote_retrieve_response_code( $response );
	$html         = (string) wp_remote_retrieve_body( $response );
	$content_type = (string) wp_remote_retrieve_header( $response, 'content-type' );

	// capture X-Robots-Tag header too (many sites use it)
	$x_robots_tag = (string) wp_remote_retrieve_header( $response, 'x-robots-tag' );

	if ( $status < 200 || $status >= 400 ) {
		return rest_ensure_response(
			[
				'url'            => $target_url,
				'meta_available' => false,
				'message'        => 'Non-success HTTP status returned.',
				'http_status'    => $status,
				'x_robots_tag'   => '' !== $x_robots_tag ? $x_robots_tag : null,
			]
		);
	}

	// If it's not HTML, meta tags may not exist.
	if ( '' !== $content_type && false === stripos( $content_type, 'text/html' ) ) {
		return rest_ensure_response(
			[
				'url'            => $target_url,
				'meta_available' => false,
				'message'        => 'Response is not HTML, cannot reliably scan <meta> tags.',
				'http_status'    => $status,
				'content_type'   => $content_type,
				'x_robots_tag'   => '' !== $x_robots_tag ? $x_robots_tag : null,
			]
		);
	}

	// Parse HTML and collect ALL <meta name="robots" content="...">
	libxml_use_internal_errors( true );
	$dom = new DOMDocument();

	// Suppress warnings from imperfect HTML.
	// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
	@$dom->loadHTML( $html );

	$metas    = $dom->getElementsByTagName( 'meta' );
	$found    = false;
	$contents = [];

	foreach ( $metas as $meta ) {
		if ( 0 === strcasecmp( $meta->getAttribute( 'name' ), 'robots' ) ) {
			$found = true;

			$meta_content = trim( (string) $meta->getAttribute( 'content' ) );
			if ( '' !== $meta_content ) {
				$contents[] = $meta_content;
			}
		}
	}

	if ( $found && ! empty( $contents ) ) {
		// normalize, split by comma, trim, dedupe, then join nicely.
		$directives = [];
		foreach ( $contents as $content_string ) {
			foreach ( explode( ',', (string) $content_string ) as $part ) {
				$d = trim( (string) $part );
				if ( '' !== $d ) {
					$directives[] = $d;
				}
			}
		}

		$directives     = array_values( array_unique( $directives ) );
		$merged_content = implode( ', ', $directives );

		return rest_ensure_response(
			[
				'url'            => $target_url,
				'meta_available' => true,
				'content'        => $merged_content,
				'http_status'    => $status,
				'x_robots_tag'   => '' !== $x_robots_tag ? $x_robots_tag : null,
			]
		);
	}

	return rest_ensure_response(
		[
			'url'            => $target_url,
			'meta_available' => false,
			'message'        => 'No robots meta tag found in this page <head>.',
			'http_status'    => $status,
			'x_robots_tag'   => '' !== $x_robots_tag ? $x_robots_tag : null,
		]
	);
}

/**
 * POST /myaio/v1/generate-robots-meta
 * Body params:
 * - key (required)    [validated by shared util]
 * - enable (optional bool, default true)
 * - content (optional string, default "index, follow")
 *
 * Stores options and outputs <meta name="robots" ...> in wp_head.
 *
 * @param WP_REST_Request $request Request.
 * @return WP_REST_Response|array
 */
function myaio_generate_robots_meta( WP_REST_Request $request ) {

	$enable  = $request->get_param( 'enable' );
	$content = (string) $request->get_param( 'content' );

	// Defaults.
	if ( null === $enable ) {
		$enable = true;
	}
	$enable = (bool) $enable;

	$content = trim( $content );
	if ( '' === $content ) {
		$content = 'index, follow';
	}

	// Store flag + content in DB (keep option keys unchanged for compatibility).
	update_option( 'sac_enable_robots_meta', $enable ? '1' : '0', false );
	update_option( 'sac_robots_meta_content', $content, false );

	return rest_ensure_response(
		[
			'success' => true,
			'enabled' => $enable,
			'content' => $content,
			'message' => $enable
				? 'robots meta tag will now be added to <head>.'
				: 'robots meta tag output has been disabled.',
		]
	);
}

/**
 * Output robots meta tag in <head> if enabled.
 */
add_action(
	'wp_head',
	function () {
		$enabled = get_option( 'sac_enable_robots_meta', '0' );
		if ( '1' !== (string) $enabled ) {
			return;
		}

		$content = (string) get_option( 'sac_robots_meta_content', 'index, follow' );
		$content = trim( $content );
		if ( '' === $content ) {
			$content = 'index, follow';
		}

		echo '<meta name="robots" content="' . esc_attr( $content ) . '">' . "\n";
	},
	1
);