<?php
// File: modules/page-explorer.php
// Compatible with PHP 7.4+ (no str_starts_with, no nullsafe operator)

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

add_action(
	'rest_api_init',
	function () {
		register_rest_route(
			'myaio/v1',
			'/page-explorer',
			array(
				'methods'             => 'GET',
				'callback'            => 'myaio_sac_page_explorer_handler',
				'permission_callback' => function ( WP_REST_Request $request ) {
					if ( function_exists( 'myaio_sac_rest_permission_check' ) ) {
						return myaio_sac_rest_permission_check( $request );
					}
					return new WP_Error( 'unauthorized', 'Auth utilities not loaded', array( 'status' => 401 ) );
				},
			)
		);
	}
);

function myaio_sac_page_explorer_handler( WP_REST_Request $request ) {

	// Optional pagination to reduce timeouts on large sites
	$per_page = (int) $request->get_param( 'per_page' );
	$page     = (int) $request->get_param( 'page' );

	if ( $per_page <= 0 ) {
    $per_page = 25;
}

$per_page = min( $per_page, 25 );
	if ( $page <= 0 ) {
		$page = 1;
	}

	$offset = ( $page - 1 ) * $per_page;

	$query_args = array(
		'post_type'         => array( 'page', 'post' ),
		'post_status'       => 'publish',
		'numberposts'       => $per_page,
		'offset'            => $offset,
		'orderby'           => 'ID',
		'order'             => 'ASC',
		'suppress_filters'  => false,
	);

	$posts = get_posts( $query_args );

	$sitemap_urls = myaio_sac_get_sitemap_urls();
	$results      = array();

	foreach ( (array) $posts as $post ) {
		$url     = get_permalink( $post );
		$title   = get_the_title( $post );
		// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- 'the_content' is a core WordPress hook.
		$content = apply_filters( 'the_content', $post->post_content );

		// Remote checks (can fail on some hosts/WAFs)
		$status = myaio_sac_get_http_status( $url );

		// Parse meta/H1/images from the *content* (not the full rendered head)
		$meta      = myaio_sac_extract_meta_from_content( $content );
		$h1        = isset( $meta['h1'] ) ? $meta['h1'] : '';
		$desc      = isset( $meta['description'] ) ? $meta['description'] : '';
		$canonical = isset( $meta['canonical'] ) ? $meta['canonical'] : '';
		$robots    = isset( $meta['robots'] ) ? $meta['robots'] : '';
		$images    = isset( $meta['images'] ) ? $meta['images'] : array();

		$depth = substr_count( str_replace( home_url(), '', (string) $url ), '/' );
		$type  = get_post_mime_type( $post->ID );
		if ( empty( $type ) ) {
			$type = 'text/html; charset=utf-8';
		}

		$importance = myaio_sac_calculate_importance_score( $post, $url );
		$health     = myaio_sac_calculate_page_health_score( $url, $content, $status, $robots, $canonical, $title, $h1, $images );

		$results[] = array(
			'url'              => $url,
			'depth'            => $depth,
			'type'             => $type,
			'importance'       => $importance,
			'page_health'      => $health,
			'https'            => ( strpos( (string) $url, 'https://' ) === 0 ) ? 'Yes' : 'No',
			'status_code'      => (int) $status,
			'title'            => $title,
			'meta_description' => $desc,
			'h1'               => $h1,
			'page_category'    => myaio_sac_classify_page_type( $url ),
			'indexable'        => ( stripos( (string) $robots, 'noindex' ) === false ),
			'in_sitemap'       => in_array( $url, $sitemap_urls, true ) ? 'Yes' : 'No',
			'linked'           => myaio_sac_is_page_linked( $post->ID ) ? 'Yes' : 'No',
			'internal_inlinks' => myaio_sac_count_internal_links_to( $url ),
			'hreflang'         => myaio_sac_get_hreflang_for_url( $url ),
		);
	}

	$total = (int) wp_count_posts( 'post' )->publish + (int) wp_count_posts( 'page' )->publish;

	return rest_ensure_response(
		array(
			'results'   => $results,
			'page'      => $page,
			'per_page'  => $per_page,
			'returned'  => count( $results ),
			'total_est' => $total,
			'next_page' => ( count( $results ) === $per_page ) ? ( $page + 1 ) : null,
		)
	);
}

// ============== HELPERS ==============

function myaio_sac_get_http_status( $url ) {
	$args = array(
		'timeout'     => 10,
		'redirection' => 5,
		'user-agent'  => 'MyAIO-PageExplorer/1.0; ' . home_url(),
	);

	$res = wp_remote_head( $url, $args );
	if ( is_wp_error( $res ) ) {
		$res = wp_remote_get( $url, $args );
	}

	return is_wp_error( $res ) ? 0 : (int) wp_remote_retrieve_response_code( $res );
}

function myaio_sac_extract_meta_from_content( $html ) {
	// NOTE: This parses meta tags *inside post content* only.
	// SEO meta/canonical is usually in <head> and won't be present here.

	libxml_use_internal_errors( true );
	$dom = new DOMDocument();

	if ( ! is_string( $html ) ) {
		$html = '';
	}

	// Load as HTML fragment
	@$dom->loadHTML( '<?xml encoding="utf-8" ?>' . $html );
	$xpath = new DOMXPath( $dom );

	$h1     = '';
	$h1Node = $xpath->query( '//h1' )->item( 0 );
	if ( $h1Node ) {
		$h1 = trim( (string) $h1Node->textContent );
	}

	$desc      = '';
	$robots    = '';
	$canonical = '';
	$images    = array();

	foreach ( $xpath->query( '//meta' ) as $meta ) {
		/** @var DOMElement $meta */
		$nameAttr = strtolower( (string) $meta->getAttribute( 'name' ) );
		$propAttr = strtolower( (string) $meta->getAttribute( 'property' ) );
		$content  = (string) $meta->getAttribute( 'content' );

		if ( 'description' === $nameAttr ) {
			$desc = $content;
		}
		if ( 'robots' === $nameAttr ) {
			$robots = $content;
		}
		if ( 'og:url' === $propAttr ) {
			$canonical = $content;
		}
	}

	$canonNode = $xpath->query( '//link[@rel="canonical"]' )->item( 0 );
	if ( $canonNode instanceof DOMElement ) {
		$href = (string) $canonNode->getAttribute( 'href' );
		if ( '' !== $href ) {
			$canonical = $href;
		}
	}

	foreach ( $xpath->query( '//img' ) as $img ) {
		/** @var DOMElement $img */
		$images[] = array(
			'src' => (string) $img->getAttribute( 'src' ),
			'alt' => (string) $img->getAttribute( 'alt' ),
		);
	}

	return array(
		'h1'          => $h1,
		'description' => $desc,
		'robots'      => $robots,
		'canonical'   => $canonical,
		'images'      => $images,
	);
}

function myaio_sac_get_sitemap_urls() {
	$sitemap_url = home_url( '/sitemap.xml' );
	$response    = wp_remote_get(
		$sitemap_url,
		array(
			'timeout'     => 15,
			'redirection' => 5,
			'user-agent'  => 'MyAIO-PageExplorer/1.0; ' . home_url(),
		)
	);

	if ( is_wp_error( $response ) ) {
		return array();
	}

	$body = wp_remote_retrieve_body( $response );
	if ( empty( $body ) ) {
		return array();
	}

	libxml_use_internal_errors( true );
	$xml = simplexml_load_string( $body );
	if ( ! $xml ) {
		return array();
	}

	$urls = array();

	if ( isset( $xml->url ) ) {
		foreach ( $xml->url as $entry ) {
			if ( ! empty( $entry->loc ) ) {
				$urls[] = (string) $entry->loc;
			}
		}
		return $urls;
	}

	if ( isset( $xml->sitemap ) ) {
		foreach ( $xml->sitemap as $s ) {
			$child = isset( $s->loc ) ? (string) $s->loc : '';
			if ( empty( $child ) ) {
				continue;
			}

			$child_res = wp_remote_get(
				$child,
				array(
					'timeout'     => 15,
					'redirection' => 5,
					'user-agent'  => 'MyAIO-PageExplorer/1.0; ' . home_url(),
				)
			);
			if ( is_wp_error( $child_res ) ) {
				continue;
			}

			$child_body = wp_remote_retrieve_body( $child_res );
			if ( empty( $child_body ) ) {
				continue;
			}

			$child_xml = simplexml_load_string( $child_body );
			if ( $child_xml && isset( $child_xml->url ) ) {
				foreach ( $child_xml->url as $entry ) {
					if ( ! empty( $entry->loc ) ) {
						$urls[] = (string) $entry->loc;
					}
				}
			}
		}
	}

	return array_values( array_unique( $urls ) );
}

function myaio_sac_classify_page_type( $url ) {
	if ( strpos( (string) $url, '/product/' ) !== false ) {
		return 'Product';
	}
	if ( strpos( (string) $url, '/category/' ) !== false ) {
		return 'Category';
	}
	if ( strpos( (string) $url, '/blog/' ) !== false ) {
		return 'Blog';
	}
	if ( strpos( (string) $url, '/about' ) !== false || strpos( (string) $url, '/contact' ) !== false ) {
		return 'Utility';
	}
	return 'Page';
}

/**
 * Cached count of posts whose post_content contains $url.
 * (Used by sac_is_page_linked and sac_count_internal_links_to)
 */
function myaio_sac_cached_posts_content_like_count( $url ) {
	global $wpdb;

	$url = (string) $url;
	if ( '' === $url ) {
		return 0;
	}

	$cache_key = 'myaio_like_cnt:' . md5( $url );
	$cached    = wp_cache_get( $cache_key, 'myaio_page_explorer' );
	if ( false !== $cached ) {
		return (int) $cached;
	}

	$like = '%' . $wpdb->esc_like( $url ) . '%';

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Cached via wp_cache_* above.
	$count = (int) $wpdb->get_var(
		$wpdb->prepare(
			'SELECT COUNT(*) FROM %i WHERE post_content LIKE %s',
			$wpdb->posts,
			$like
		)
	);

	wp_cache_set( $cache_key, $count, 'myaio_page_explorer', 300 );

	return $count;
}

function myaio_sac_is_page_linked( $post_id ) {
	$url = get_permalink( $post_id );
	return myaio_sac_cached_posts_content_like_count( $url ) > 0;
}

function myaio_sac_count_internal_links_to( $url ) {
	return myaio_sac_cached_posts_content_like_count( $url );
}

function myaio_sac_get_hreflang_for_url( $url ) {
	$res = wp_remote_get(
		$url,
		array(
			'timeout'     => 12,
			'redirection' => 5,
			'user-agent'  => 'MyAIO-PageExplorer/1.0; ' . home_url(),
		)
	);

	if ( is_wp_error( $res ) ) {
		return array( 'error' => 'Failed to fetch URL' );
	}

	$html = wp_remote_retrieve_body( $res );
	if ( empty( $html ) ) {
		return array( 'error' => 'Empty page content' );
	}

	libxml_use_internal_errors( true );
	$dom = new DOMDocument();
	@$dom->loadHTML( $html );

	$hreflangs = array();
	$links     = $dom->getElementsByTagName( 'link' );

	foreach ( $links as $link ) {
		/** @var DOMElement $link */
		if ( strtolower( (string) $link->getAttribute( 'rel' ) ) === 'alternate' ) {
			$hreflang = (string) $link->getAttribute( 'hreflang' );
			$href     = (string) $link->getAttribute( 'href' );
			if ( '' !== $hreflang && '' !== $href ) {
				$hreflangs[ $hreflang ] = $href;
			}
		}
	}

	return ! empty( $hreflangs ) ? $hreflangs : array( 'message' => 'Not Present' );
}

// ============== SCORING FUNCTIONS ==============

function myaio_sac_calculate_importance_score( $post, $url ) {
	$score = 0;

	$inlinks = myaio_sac_count_internal_links_to( $url );
	$score  += min( $inlinks / 5, 1 ) * 20;

	$score += min( $inlinks / 5, 1 ) * 10;

	$score += 3;

	$score += myaio_sac_is_page_linked( $post->ID ) ? 5 : 0;

	$depth  = substr_count( str_replace( home_url(), '', (string) $url ), '/' );
	$score += 10 * max( 0, 1 - ( $depth / 6 ) );

	$score += 5;

	$score += 7;

	$score += 3;

	$score += 4;

	$score += 5;

	$score += 5;

	return min( 100, (int) round( $score ) );
}

function myaio_sac_calculate_page_health_score( $url, $html, $status, $robots, $canonical, $title, $h1, $images ) {
	$score = 0;

	$score += ( (int) $status === 200 ? 10 : 0 );
	$score += ( stripos( (string) $robots, 'noindex' ) === false ? 8 : 0 );
	$score += ( ! empty( $canonical ) ? 6 : 0 );
	$score += ( strpos( (string) $url, 'https://' ) === 0 ? 6 : 0 );

	$score += ( ! empty( $title ) ? 7 : 0 );
	$score += ( ! empty( $h1 ) ? 7 : 0 );
	$score += 4;
	$score += 2;

	$score += 20;

	$score += 8;

	$score += 6;

	$score += 5;

	$score += 4;

	return min( 100, (int) round( $score ) );
}