<?php
/**
 * Livada SEO — Robots Module
 *
 * Manages the virtual robots.txt file served by WordPress.
 * Reads the stored content from settings, replaces the `%siteurl%` token
 * with the site's home URL, and injects the result via the `robots_txt` filter.
 *
 * Default content (set at activation):
 *   User-agent: *
 *   Allow: /
 *   Sitemap: %siteurl%/sitemap.xml
 *
 * @package Livada_SEO
 */

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

class Livada_SEO_Robots {

	// ── Bootstrap ─────────────────────────────────────────────────────────────

	/**
	 * Registers all hooks for this module.
	 * Called once by Livada_SEO_Loader::load_class().
	 */
	public static function init(): void {
		add_filter( 'robots_txt', [ __CLASS__, 'filter_robots_txt' ], 10, 2 );
	}

	// ── Filter ────────────────────────────────────────────────────────────────

	/**
	 * Replaces the default WordPress robots.txt output with the stored setting.
	 *
	 * The `%siteurl%` token is replaced with `home_url()` so the sitemap URL
	 * is always correct regardless of the domain the site runs on.
	 *
	 * @param  string $output  The default robots.txt content produced by WordPress.
	 * @param  bool   $public  Whether the site is set to be visible to search engines.
	 * @return string          The filtered robots.txt content.
	 */
	public static function filter_robots_txt( string $output, bool $public ): string {
		$content = (string) Livada_SEO_Loader::get_setting(
			'robots_txt',
			"User-agent: *\nAllow: /\nSitemap: %siteurl%/sitemap.xml"
		);

		// Replace the siteurl token with the actual home URL (no trailing slash).
		$content = str_replace( '%siteurl%', untrailingslashit( home_url() ), $content );

		// Normalise line endings: collapse CRLF / CR variants down to LF.
		$content = str_replace( [ "\r\n", "\r" ], "\n", $content );

		// Defensive split: when the stored content has no newlines (DB export
		// quirk, manual paste without breaks, etc.) directives end up glued on
		// a single line. Inject a newline before every well-known directive
		// keyword so the served robots.txt stays human-readable.
		if ( false === strpos( $content, "\n" ) ) {
			$content = (string) preg_replace(
				'/\s*\b(User-agent:|Allow:|Disallow:|Sitemap:|Crawl-delay:|Host:)/i',
				"\n$1",
				$content
			);
			$content = ltrim( $content, "\n" );
		}

		// Append the AI Bots Access Control block (Livada SEO 1.12+).
		// We only append when the AI Bots module is wired in (avoids fatal
		// errors during partial deploys) and when the user hasn't already
		// pasted their own block (idempotent on re-saves).
		if (
			class_exists( 'Livada_SEO_AI_Bots' )
			&& false === stripos( $content, '# Livada SEO — AI bot access' )
		) {
			$content .= "\n" . Livada_SEO_AI_Bots::build_robots_block();
		}

		// Trim trailing whitespace per directive line + ensure a single
		// trailing newline (RFC 9309 prefers it).
		$lines = array_map( 'rtrim', explode( "\n", $content ) );
		return implode( "\n", $lines ) . "\n";
	}
}
