<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * REST API: /wp-json/myaio/v1/schema-scan
 *
 * Query params:
 * - url (string) optional
 *
 * Auth:
 * - Shared permission callback:
 *   myaio_sac_rest_permission_check( WP_REST_Request $request )
 */

add_action(
	'rest_api_init',
	function () {
		register_rest_route(
			'myaio/v1',
			'/schema-scan',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => 'myaio_schema_scan',
				'permission_callback' => 'myaio_sac_rest_permission_check',
				'args'                => array(
					'url' => array(
						'type'              => 'string',
						'required'          => false,
						'sanitize_callback' => 'sanitize_text_field',
					),
				),
			)
		);
	}
);

/**
 * Normalize requested URL.
 *
 * Supports:
 * - full URL
 * - root-relative path like /about-us
 *
 * @param string|null $requested Requested URL.
 * @return string
 */
function myaio_schema_scan_normalize_requested_url( $requested ) {
	$requested = trim( (string) $requested );

	if ( '' === $requested ) {
		return '';
	}

	if ( 0 === strpos( $requested, '/' ) ) {
		$requested = home_url( $requested );
	}

	return rtrim( esc_url_raw( $requested ), '/' );
}

/**
 * Normalize URL for comparisons.
 *
 * @param string $url URL.
 * @return string
 */
function myaio_schema_scan_normalize_url_for_compare( $url ) {
	$url = trim( (string) $url );
	if ( '' === $url ) {
		return '';
	}

	$parts = wp_parse_url( $url );
	if ( ! is_array( $parts ) ) {
		return rtrim( $url, '/' );
	}

	$scheme = isset( $parts['scheme'] ) ? strtolower( (string) $parts['scheme'] ) : 'http';
	$host   = isset( $parts['host'] ) ? strtolower( (string) $parts['host'] ) : '';
	$port   = isset( $parts['port'] ) ? ':' . $parts['port'] : '';
	$path   = isset( $parts['path'] ) ? (string) $parts['path'] : '';
	$query  = isset( $parts['query'] ) ? '?' . $parts['query'] : '';
	$frag   = isset( $parts['fragment'] ) ? '#' . $parts['fragment'] : '';

	if ( '/' !== $path ) {
		$path = rtrim( $path, '/' );
	}

	return $scheme . '://' . $host . $port . $path . $query . $frag;
}

/**
 * Build crawlable URL list, optionally restricted to one URL.
 *
 * Preserves type/category when available.
 *
 * @param string $requested_url Requested URL.
 * @return array
 */
function myaio_schema_scan_get_filtered_urls( $requested_url = '' ) {
	if ( function_exists( 'myaio_sac_get_all_crawlable_urls' ) ) {
		$all_urls = myaio_sac_get_all_crawlable_urls();
	} elseif ( function_exists( 'myaio_sac_get_all_site_urls' ) ) {
		$all_urls = myaio_sac_get_all_site_urls();
	} else {
		return array();
	}

	if ( ! is_array( $all_urls ) ) {
		return array();
	}

	if ( '' === $requested_url ) {
		return $all_urls;
	}

	$requested_norm = myaio_schema_scan_normalize_url_for_compare( $requested_url );
	$matched        = null;

	foreach ( $all_urls as $item ) {
		if ( ! is_array( $item ) || empty( $item['url'] ) ) {
			continue;
		}

		$item_url = myaio_schema_scan_normalize_url_for_compare( (string) $item['url'] );
		if ( $item_url === $requested_norm ) {
			$matched = $item;
			break;
		}
	}

	if ( null !== $matched ) {
		return array( $matched );
	}

	return array(
		array(
			'url'      => $requested_url,
			'type'     => null,
			'category' => null,
		),
	);
}

/**
 * MAIN CALLBACK
 *
 * @param WP_REST_Request $request Request.
 * @return WP_REST_Response
 */
function myaio_schema_scan( WP_REST_Request $request ) {
	$http_timeout  = 30;
	$requested_url = myaio_schema_scan_normalize_requested_url( $request->get_param( 'url' ) );
	$all_urls      = myaio_schema_scan_get_filtered_urls( $requested_url );

	if ( '' === $requested_url ) {
		if ( function_exists( 'myaio_sac_get_all_crawlable_urls' ) || function_exists( 'myaio_sac_get_all_site_urls' ) ) {
			// continue
		} else {
			return rest_ensure_response(
				array(
					'error' => 'No crawlable URL provider found (myaio_sac_get_all_crawlable_urls / myaio_sac_get_all_site_urls)',
				)
			);
		}
	} elseif ( empty( $all_urls ) ) {
		$all_urls = array(
			array(
				'url'      => $requested_url,
				'type'     => null,
				'category' => null,
			),
		);
	}

	if ( ! is_array( $all_urls ) ) {
		$all_urls = array();
	}

	$results           = array();
	$total_with_schema = 0;

	if ( ! class_exists( 'DOMDocument' ) || ! class_exists( 'DOMXPath' ) ) {
		return rest_ensure_response(
			array(
				'error' => 'DOM extension not available',
			)
		);
	}

	foreach ( $all_urls as $url_data ) {
		$page_url = '';
		if ( is_array( $url_data ) && isset( $url_data['url'] ) ) {
			$page_url = (string) $url_data['url'];
		}

		$page_url = esc_url_raw( trim( $page_url ) );
		if ( '' === $page_url ) {
			continue;
		}

		$type     = ( is_array( $url_data ) && isset( $url_data['type'] ) ) ? sanitize_text_field( (string) $url_data['type'] ) : '';
		$category = ( is_array( $url_data ) && isset( $url_data['category'] ) ) ? sanitize_text_field( (string) $url_data['category'] ) : '';

		$response = wp_remote_get(
			$page_url,
			array(
				'timeout'     => $http_timeout,
				'redirection' => 5,
				'headers'     => array(
					'User-Agent' => 'MYAIO-Schema-Scanner/1.0; ' . home_url(),
					'Accept'     => 'text/html,application/xhtml+xml',
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			$results[] = array(
				'url'      => $page_url,
				'type'     => $type,
				'category' => $category,
				'error'    => $response->get_error_message(),
			);
			continue;
		}

		$code = (int) wp_remote_retrieve_response_code( $response );
		if ( $code < 200 || $code >= 300 ) {
			$results[] = array(
				'url'      => $page_url,
				'type'     => $type,
				'category' => $category,
				'error'    => 'HTTP ' . $code,
			);
			continue;
		}

		$html = (string) wp_remote_retrieve_body( $response );
		if ( '' === $html ) {
			$results[] = array(
				'url'      => $page_url,
				'type'     => $type,
				'category' => $category,
				'error'    => 'Empty HTML',
			);
			continue;
		}

		libxml_use_internal_errors( true );

		$dom    = new DOMDocument();
		$loaded = $dom->loadHTML( '<?xml encoding="utf-8" ?>' . $html, LIBXML_NOWARNING | LIBXML_NOERROR );

		if ( ! $loaded ) {
			libxml_clear_errors();
			$results[] = array(
				'url'      => $page_url,
				'type'     => $type,
				'category' => $category,
				'error'    => 'Failed to parse HTML',
			);
			continue;
		}

		// Extract full raw JSON-LD blocks.
		$jsonld_blocks = array();
		$scripts       = $dom->getElementsByTagName( 'script' );

		foreach ( $scripts as $script ) {
			if ( ! $script instanceof DOMElement ) {
				continue;
			}

			$type_attr = trim( (string) $script->getAttribute( 'type' ) );
			if ( 'application/ld+json' === strtolower( $type_attr ) ) {
				$content = trim( (string) $script->textContent );
				if ( '' !== $content ) {
					$jsonld_blocks[] = $content;
				}
			}
		}

		$xpath = new DOMXPath( $dom );

		// Basic microdata detection.
		$microdata_nodes = $xpath->query( '//*[@itemscope or @itemtype]' );
		$has_microdata   = ( $microdata_nodes && $microdata_nodes->length > 0 );

		// Basic RDFa detection.
		$rdfa_nodes = $xpath->query( '//*[@typeof or @vocab]' );
		$has_rdfa   = ( $rdfa_nodes && $rdfa_nodes->length > 0 );

		libxml_clear_errors();

		$has_schema = ( ! empty( $jsonld_blocks ) || $has_microdata || $has_rdfa );

		if ( $has_schema ) {
			$total_with_schema++;
		}

		$results[] = array(
			'url'           => $page_url,
			'type'          => $type,
			'category'      => $category,
			'has_schema'    => $has_schema,
			'has_jsonld'    => ! empty( $jsonld_blocks ),
			'has_microdata' => $has_microdata,
			'has_rdfa'      => $has_rdfa,
			'jsonld'        => $jsonld_blocks,
		);
	}

	$total_available = count( $all_urls );

	return rest_ensure_response(
		array(
			'summary' => array(
				'total_urls_available' => $total_available,
				'limit'                => $total_available,
				'offset'               => 0,
				'scanned_this_call'    => $total_available,
				'pages_with_schema'    => $total_with_schema,
			),
			'pages'   => $results,
			'next'    => array(
				'offset' => null,
				'limit'  => $total_available,
			),
		)
	);
}