<?php
/**
 * Yoast SEO integration — extends Yoast's schema graph with the plugin's
 * vehicle/dealer pieces (per ADR-19, mode 2).
 *
 * Yoast already emits `WebPage`, `BreadcrumbList`, `Organization`/`WebSite`
 * for every page. We add `Car`/`Vehicle`/`Motorcycle` + `Offer` on single
 * vehicles, `AutoDealer` on single dealers, and `FAQPage` if FAQ entries
 * exist. Yoast's BreadcrumbList stays — we don't double up.
 *
 * Yoast prefers an array of "graph piece" *class instances* with a
 * `generate()` method; for one-shot static pieces it's simpler to add
 * the JSON directly via `wpseo_schema_graph` filter, which is exactly
 * what we do here.
 *
 * @package ThemeREX\AutoDealer
 */

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Integrations\Yoast;

defined( 'ABSPATH' ) || exit;
use ThemeREX\AutoDealer\Integrations\Schema\SchemaGenerator;

class YoastIntegration {

	public function register(): void {
		add_filter( 'wpseo_schema_graph', array( $this, 'extendGraph' ), 11, 1 );
	}

	/**
	 * Append plugin pieces to Yoast's `@graph` array.
	 *
	 * Source of pieces is `SchemaGenerator::buildGraph()` so anything
	 * registered through the `trx_ad_schema_graph_pieces` filter (Phase 18
	 * AEO/GEO modules add WebSite, ItemList, Dataset, Speakable, etc.
	 * through that hook) flows through automatically. We strip
	 * `BreadcrumbList` because Yoast emits its own.
	 *
	 * @param array<int, array<string, mixed>>|mixed $graph
	 * @return array<int, array<string, mixed>>
	 */
	public function extendGraph( $graph ): array {
		if ( ! is_array( $graph ) ) {
			$graph = array();
		}

		$additions = array();
		foreach ( SchemaGenerator::buildGraph() as $piece ) {
			if ( ! is_array( $piece ) ) {
				continue;
			}
			$type = $piece['@type'] ?? '';
			// Yoast emits its own BreadcrumbList — skip ours.
			if ( 'BreadcrumbList' === $type ) {
				continue;
			}
			if ( self::graphHasId( $graph, $piece['@id'] ?? '' ) ) {
				continue;
			}
			$additions[] = $piece;
		}

		if ( empty( $additions ) ) {
			return $graph;
		}

		return array_merge( $graph, $additions );
	}

	/**
	 * Avoid pushing a piece whose `@id` already exists in the graph (some
	 * Yoast extensions duplicate WebPage/Organization nodes; treat any
	 * `@id` collision as a "skip" so we don't fight them).
	 *
	 * @param array<int, array<string, mixed>> $graph
	 */
	private static function graphHasId( array $graph, string $id ): bool {
		if ( '' === $id ) {
			return false;
		}
		foreach ( $graph as $node ) {
			if ( is_array( $node ) && isset( $node['@id'] ) && $node['@id'] === $id ) {
				return true;
			}
		}
		return false;
	}
}
