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

interface SftcyWordaiSeoProviderInterface {
	public function get_id();
	public function get_label();
	public function is_active();
	public function get_version();
	public function read( $post_id );
	public function write( $post_id, array $document );
}

abstract class SftcyWordaiSeoMetaProvider implements SftcyWordaiSeoProviderInterface {
	protected function value( $post_id, $key ) {
		return (string) get_post_meta( $post_id, $key, true );
	}

	protected function save_value( $post_id, $key, $value ) {
		if ( '' === (string) $value ) {
			delete_post_meta( $post_id, $key );
			return;
		}

		update_post_meta( $post_id, $key, $value );
	}

	protected function base_document( $post_id ) {
		return SftcyWordaiSeoIntegrationManager::normalize_document(
			array(
				'provider'      => $this->get_id(),
				'provider_name' => $this->get_label(),
				'provider_version' => $this->get_version(),
				'canonical'     => get_permalink( $post_id ),
			)
		);
	}
}

class SftcyWordaiSeoNativeAdapter extends SftcyWordaiSeoMetaProvider {
	public function get_id() { return 'native'; }
	public function get_label() { return 'WordAI Native'; }
	public function is_active() { return true; }
	public function get_version() { return defined( 'SFTCY_WORDAI_VERSION' ) ? SFTCY_WORDAI_VERSION : ''; }

	public function read( $post_id ) {
		$document = $this->base_document( $post_id );
		$document['title']         = $this->value( $post_id, '_wordai_seo_title' );
		$document['description']   = $this->value( $post_id, '_wordai_seo_meta_description' );
		$document['focus_keyword'] = $this->value( $post_id, '_wordai_seo_focus_keyword' );
		$document['canonical']     = $this->value( $post_id, '_wordai_seo_canonical_url' ) ?: get_permalink( $post_id );
		$document['robots']        = $this->value( $post_id, '_wordai_seo_robots_meta' ) ?: 'index,follow';
		$document['schema_type']   = $this->value( $post_id, '_wordai_seo_schema_type' );

		return SftcyWordaiSeoIntegrationManager::normalize_document( $document );
	}

	public function write( $post_id, array $document ) {
		$document = SftcyWordaiSeoIntegrationManager::normalize_document( $document );
		$map = array(
			'title'         => '_wordai_seo_title',
			'description'   => '_wordai_seo_meta_description',
			'focus_keyword' => '_wordai_seo_focus_keyword',
			'canonical'     => '_wordai_seo_canonical_url',
			'robots'        => '_wordai_seo_robots_meta',
			'schema_type'   => '_wordai_seo_schema_type',
		);

		foreach ( $map as $field => $meta_key ) {
			$this->save_value( $post_id, $meta_key, $document[ $field ] );
		}

		return true;
	}
}

class SftcyWordaiSeoYoastAdapter extends SftcyWordaiSeoMetaProvider {
	public function get_id() { return 'yoast'; }
	public function get_label() { return 'Yoast SEO'; }
	public function is_active() { return defined( 'WPSEO_VERSION' ) || class_exists( 'WPSEO_Options' ); }
	public function get_version() { return defined( 'WPSEO_VERSION' ) ? WPSEO_VERSION : ''; }

	public function read( $post_id ) {
		$document = $this->base_document( $post_id );
		$document['title']         = $this->value( $post_id, '_yoast_wpseo_title' );
		$document['description']   = $this->value( $post_id, '_yoast_wpseo_metadesc' );
		$document['focus_keyword'] = $this->value( $post_id, '_yoast_wpseo_focuskw' );
		$document['canonical']     = $this->value( $post_id, '_yoast_wpseo_canonical' ) ?: get_permalink( $post_id );
		$document['robots']        = ( '1' === $this->value( $post_id, '_yoast_wpseo_meta-robots-noindex' ) ? 'noindex' : 'index' ) . ',' . ( '1' === $this->value( $post_id, '_yoast_wpseo_meta-robots-nofollow' ) ? 'nofollow' : 'follow' );
		$document['schema_type']   = $this->value( $post_id, '_yoast_wpseo_schema_article_type' ) ?: $this->value( $post_id, '_yoast_wpseo_schema_page_type' );

		return SftcyWordaiSeoIntegrationManager::normalize_document( $document );
	}

	public function write( $post_id, array $document ) {
		$document = SftcyWordaiSeoIntegrationManager::normalize_document( $document );
		$this->save_value( $post_id, '_yoast_wpseo_title', $document['title'] );
		$this->save_value( $post_id, '_yoast_wpseo_metadesc', $document['description'] );
		$this->save_value( $post_id, '_yoast_wpseo_focuskw', $document['focus_keyword'] );
		$this->save_value( $post_id, '_yoast_wpseo_canonical', $document['canonical'] );
		$this->save_value( $post_id, '_yoast_wpseo_meta-robots-noindex', false !== strpos( $document['robots'], 'noindex' ) ? '1' : '' );
		$this->save_value( $post_id, '_yoast_wpseo_meta-robots-nofollow', false !== strpos( $document['robots'], 'nofollow' ) ? '1' : '' );
		$this->save_value( $post_id, '_yoast_wpseo_schema_article_type', $document['schema_type'] );
		clean_post_cache( $post_id );

		return true;
	}
}

class SftcyWordaiSeoRankMathAdapter extends SftcyWordaiSeoMetaProvider {
	public function get_id() { return 'rank_math'; }
	public function get_label() { return 'Rank Math SEO'; }
	public function is_active() { return defined( 'RANK_MATH_VERSION' ) || class_exists( 'RankMath' ); }
	public function get_version() { return defined( 'RANK_MATH_VERSION' ) ? RANK_MATH_VERSION : ''; }

	public function read( $post_id ) {
		$document = $this->base_document( $post_id );
		$robots = get_post_meta( $post_id, 'rank_math_robots', true );
		$robots = is_array( $robots ) ? $robots : array();
		$document['title']         = $this->value( $post_id, 'rank_math_title' );
		$document['description']   = $this->value( $post_id, 'rank_math_description' );
		$document['focus_keyword'] = $this->value( $post_id, 'rank_math_focus_keyword' );
		$document['canonical']     = $this->value( $post_id, 'rank_math_canonical_url' ) ?: get_permalink( $post_id );
		$document['robots']        = ( in_array( 'noindex', $robots, true ) ? 'noindex' : 'index' ) . ',' . ( in_array( 'nofollow', $robots, true ) ? 'nofollow' : 'follow' );
		$document['schema_type']   = $this->value( $post_id, 'rank_math_rich_snippet' );

		return SftcyWordaiSeoIntegrationManager::normalize_document( $document );
	}

	public function write( $post_id, array $document ) {
		$document = SftcyWordaiSeoIntegrationManager::normalize_document( $document );
		$this->save_value( $post_id, 'rank_math_title', $document['title'] );
		$this->save_value( $post_id, 'rank_math_description', $document['description'] );
		$this->save_value( $post_id, 'rank_math_focus_keyword', $document['focus_keyword'] );
		$this->save_value( $post_id, 'rank_math_canonical_url', $document['canonical'] );
		update_post_meta(
			$post_id,
			'rank_math_robots',
			array(
				false !== strpos( $document['robots'], 'noindex' ) ? 'noindex' : 'index',
				false !== strpos( $document['robots'], 'nofollow' ) ? 'nofollow' : 'follow',
			)
		);
		$this->save_value( $post_id, 'rank_math_rich_snippet', $document['schema_type'] );
		clean_post_cache( $post_id );

		return true;
	}
}

class SftcyWordaiSeoSeopressAdapter extends SftcyWordaiSeoMetaProvider {
	public function get_id() { return 'seopress'; }
	public function get_label() { return 'SEOPress'; }
	public function is_active() { return defined( 'SEOPRESS_VERSION' ) || function_exists( 'seopress_init' ); }
	public function get_version() { return defined( 'SEOPRESS_VERSION' ) ? SEOPRESS_VERSION : ''; }

	public function read( $post_id ) {
		$document = $this->base_document( $post_id );
		$document['title']         = $this->value( $post_id, '_seopress_titles_title' );
		$document['description']   = $this->value( $post_id, '_seopress_titles_desc' );
		$document['focus_keyword'] = $this->value( $post_id, '_seopress_analysis_target_kw' );
		$document['canonical']     = $this->value( $post_id, '_seopress_robots_canonical' ) ?: get_permalink( $post_id );
		$document['robots']        = ( 'yes' === $this->value( $post_id, '_seopress_robots_index' ) ? 'noindex' : 'index' ) . ',' . ( 'yes' === $this->value( $post_id, '_seopress_robots_follow' ) ? 'nofollow' : 'follow' );

		return SftcyWordaiSeoIntegrationManager::normalize_document( $document );
	}

	public function write( $post_id, array $document ) {
		$document = SftcyWordaiSeoIntegrationManager::normalize_document( $document );
		$this->save_value( $post_id, '_seopress_titles_title', $document['title'] );
		$this->save_value( $post_id, '_seopress_titles_desc', $document['description'] );
		$this->save_value( $post_id, '_seopress_analysis_target_kw', $document['focus_keyword'] );
		$this->save_value( $post_id, '_seopress_robots_canonical', $document['canonical'] );
		$this->save_value( $post_id, '_seopress_robots_index', false !== strpos( $document['robots'], 'noindex' ) ? 'yes' : '' );
		$this->save_value( $post_id, '_seopress_robots_follow', false !== strpos( $document['robots'], 'nofollow' ) ? 'yes' : '' );
		clean_post_cache( $post_id );

		return true;
	}
}

class SftcyWordaiSeoAioseoAdapter extends SftcyWordaiSeoMetaProvider {
	public function get_id() { return 'aioseo'; }
	public function get_label() { return 'All in One SEO'; }
	public function is_active() { return defined( 'AIOSEO_VERSION' ) || function_exists( 'aioseo' ); }
	public function get_version() { return defined( 'AIOSEO_VERSION' ) ? AIOSEO_VERSION : ''; }

	private function execute( $ability_name, array $input ) {
		if ( ! function_exists( 'wp_get_ability' ) ) {
			return new WP_Error( 'wordai_aioseo_unsupported', __( 'This AIOSEO version does not expose the required compatibility API.', SftcyWordaiSeoIntegrationManager::textdomain() ) );
		}

		$ability = wp_get_ability( $ability_name );
		if ( ! $ability ) {
			return new WP_Error( 'wordai_aioseo_unsupported', __( 'The AIOSEO compatibility API is unavailable.', SftcyWordaiSeoIntegrationManager::textdomain() ) );
		}

		return $ability->execute( $input );
	}

	private function ensure_indexed( $post_id ) {
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return new WP_Error( 'wordai_aioseo_forbidden', __( 'You do not have permission to update SEO data for this content item.', SftcyWordaiSeoIntegrationManager::textdomain() ) );
		}

		if ( ! class_exists( '\\AIOSEO\\Plugin\\Common\\Models\\Post' ) ) {
			return new WP_Error( 'wordai_aioseo_unsupported', __( 'AIOSEO could not initialize its post index.', SftcyWordaiSeoIntegrationManager::textdomain() ) );
		}

		$model = \AIOSEO\Plugin\Common\Models\Post::getPost( (int) $post_id );
		if ( $model && $model->exists() ) {
			return true;
		}

		// AIOSEO's public ability requires its index row to exist. Seed the row
		// through AIOSEO's model, then keep all field reads/writes on the ability API.
		\AIOSEO\Plugin\Common\Models\Post::savePost( (int) $post_id, array( 'title' => '' ) );
		$model = \AIOSEO\Plugin\Common\Models\Post::getPost( (int) $post_id );

		return $model && $model->exists()
			? true
			: new WP_Error( 'wordai_aioseo_index_failed', __( 'AIOSEO could not create its post index.', SftcyWordaiSeoIntegrationManager::textdomain() ) );
	}

	public function read( $post_id ) {
		$result = $this->execute( 'aioseo-posts/seo-data-get', array( 'postId' => (int) $post_id ) );
		if ( is_wp_error( $result ) && 'not_found' === $result->get_error_code() ) {
			$indexed = $this->ensure_indexed( (int) $post_id );
			if ( ! is_wp_error( $indexed ) ) {
				$result = $this->execute( 'aioseo-posts/seo-data-get', array( 'postId' => (int) $post_id ) );
			}
		}
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		$robots = is_array( $result['robots'] ?? null ) ? $result['robots'] : array();
		return SftcyWordaiSeoIntegrationManager::normalize_document(
			array(
				'provider'         => $this->get_id(),
				'provider_name'    => $this->get_label(),
				'provider_version' => $this->get_version(),
				'title'            => $result['title'] ?? '',
				'description'      => $result['description'] ?? '',
				'focus_keyword'    => $result['focus_keyphrase'] ?? '',
				'canonical'        => $result['canonical_url'] ?? get_permalink( $post_id ),
				'robots'           => ( ! empty( $robots['noindex'] ) ? 'noindex' : 'index' ) . ',' . ( ! empty( $robots['nofollow'] ) ? 'nofollow' : 'follow' ),
				'schema_type'      => $result['schema_type'] ?? '',
			)
		);
	}

	public function write( $post_id, array $document ) {
		$document = SftcyWordaiSeoIntegrationManager::normalize_document( $document );
		$indexed = $this->ensure_indexed( (int) $post_id );
		if ( is_wp_error( $indexed ) ) {
			return $indexed;
		}
		$result = $this->execute(
			'aioseo-posts/seo-data-update',
			array(
				'postId'          => (int) $post_id,
				'title'           => $document['title'],
				'description'     => $document['description'],
				'canonical_url'   => $document['canonical'],
				'focus_keyphrase' => $document['focus_keyword'],
				'robots'          => array(
					'use_default' => false,
					'noindex'     => false !== strpos( $document['robots'], 'noindex' ),
					'nofollow'    => false !== strpos( $document['robots'], 'nofollow' ),
				),
			)
		);

		return is_wp_error( $result ) ? $result : true;
	}
}

class SftcyWordaiSeoIntegrationManager {
	const OPTION_PROVIDER = 'sftcy_wordai_seo_integration_provider';
	const OPTION_LAST_WRITE = 'sftcy_wordai_seo_integration_last_write';
	const NONCE_ACTION = 'scwordai_wpnonce';
	private static $providers = null;

	public static function init() {
		add_filter( 'get_canonical_url', array( __CLASS__, 'filter_native_canonical' ), 20, 2 );
		add_filter( 'wp_robots', array( __CLASS__, 'filter_native_robots' ), 20 );
		add_action( 'admin_notices', array( __CLASS__, 'render_admin_notice' ) );
		add_action( 'wp_ajax_sc_wordai_seo_integration_save', array( __CLASS__, 'ajax_save_provider' ) );
		add_filter( 'aioseo_disable', array( __CLASS__, 'disable_unselected_aioseo' ), 999 );
		add_filter( 'rank_math/frontend/disable_integration', array( __CLASS__, 'disable_unselected_rank_math' ), 999 );
		add_filter( 'wpseo_frontend_presenters', array( __CLASS__, 'disable_unselected_yoast_presenters' ), 999 );
		add_action( 'wp', array( __CLASS__, 'disable_unselected_seopress' ), 999 );
	}

	public static function textdomain() {
		return class_exists( 'SftcyWordaiFeatures' ) ? SftcyWordaiFeatures::wordai_get_textdomain() : 'wordai-pro';
	}

	public static function providers() {
		if ( null === self::$providers ) {
			self::$providers = array(
				'native'    => new SftcyWordaiSeoNativeAdapter(),
				'yoast'     => new SftcyWordaiSeoYoastAdapter(),
				'rank_math' => new SftcyWordaiSeoRankMathAdapter(),
				'aioseo'    => new SftcyWordaiSeoAioseoAdapter(),
				'seopress'  => new SftcyWordaiSeoSeopressAdapter(),
			);
		}

		return self::$providers;
	}

	public static function active_external_ids() {
		$active = array();
		foreach ( self::providers() as $id => $provider ) {
			if ( 'native' !== $id && $provider->is_active() ) {
				$active[] = $id;
			}
		}

		return $active;
	}

	public static function selected_provider_id() {
		$active = self::active_external_ids();
		$selected = sanitize_key( (string) get_option( self::OPTION_PROVIDER, 'auto' ) );

		if ( in_array( $selected, $active, true ) ) {
			return $selected;
		}
		if ( 1 === count( $active ) ) {
			return reset( $active );
		}
		if ( empty( $active ) ) {
			return 'native';
		}

		return '';
	}

	public static function status() {
		$providers = self::providers();
		$active = self::active_external_ids();
		$selected = self::selected_provider_id();
		$items = array();

		foreach ( $active as $id ) {
			$items[] = array(
				'id'      => $id,
				'label'   => $providers[ $id ]->get_label(),
				'version' => $providers[ $id ]->get_version(),
			);
		}

		$owner = isset( $providers[ $selected ] ) ? $providers[ $selected ] : null;
		return array(
			'active'       => $items,
			'selected'     => $selected,
			'selected_name'=> $owner ? $owner->get_label() : '',
			'selected_version' => $owner ? $owner->get_version() : '',
			'conflict'     => '' === $selected,
			'mode'         => (string) get_option( self::OPTION_PROVIDER, 'auto' ),
			'last_write'   => get_option( self::OPTION_LAST_WRITE, array() ),
			'supported_fields' => self::supported_fields(),
		);
	}

	public static function supported_fields() {
		$fields = array(
			'title' => true, 'description' => true, 'focus_keyword' => true,
			'canonical' => true, 'robots' => true, 'schema_type' => true,
		);
		if ( in_array( self::selected_provider_id(), array( 'aioseo', 'seopress' ), true ) ) {
			$fields['schema_type'] = false;
		}
		return $fields;
	}

	public static function has_conflict() {
		return '' === self::selected_provider_id();
	}

	public static function should_wordai_output() {
		return empty( self::active_external_ids() );
	}

	private static function should_disable_external( $provider_id ) {
		$active = self::active_external_ids();
		if ( count( $active ) < 2 || ! in_array( $provider_id, $active, true ) ) {
			return false;
		}

		return self::selected_provider_id() !== $provider_id;
	}

	public static function disable_unselected_aioseo( $disabled ) {
		return $disabled || self::should_disable_external( 'aioseo' );
	}

	public static function disable_unselected_rank_math( $disabled ) {
		return $disabled || self::should_disable_external( 'rank_math' );
	}

	public static function disable_unselected_yoast_presenters( $presenters ) {
		return self::should_disable_external( 'yoast' ) ? array() : $presenters;
	}

	public static function disable_unselected_seopress() {
		if ( ! self::should_disable_external( 'seopress' ) ) {
			return;
		}

		remove_action( 'wp_head', 'seopress_load_titles_options', 0 );
		remove_action( 'wp_head', 'seopress_load_social_options', 0 );
	}

	public static function provider() {
		$id = self::selected_provider_id();
		$providers = self::providers();
		return isset( $providers[ $id ] ) ? $providers[ $id ] : null;
	}

	public static function read( $post_id ) {
		$provider = self::provider();
		if ( ! $provider ) {
			return new WP_Error( 'wordai_seo_provider_conflict', __( 'Multiple SEO plugins are active. Select one SEO output owner before continuing.', self::textdomain() ) );
		}

		return $provider->read( (int) $post_id );
	}

	public static function write( $post_id, array $document ) {
		$provider = self::provider();
		if ( ! $provider ) {
			return new WP_Error( 'wordai_seo_provider_conflict', __( 'Multiple SEO plugins are active. Select one SEO output owner before applying changes.', self::textdomain() ) );
		}

		$existing = $provider->read( (int) $post_id );
		if ( is_wp_error( $existing ) ) {
			$existing = self::normalize_document( array() );
		}

		$managed_document = array();
		foreach ( self::supported_fields() as $field => $supported ) {
			if ( $supported && array_key_exists( $field, $document ) ) {
				$managed_document[ $field ] = $document[ $field ];
			}
		}
		$target = self::normalize_document( array_merge( $existing, $managed_document ) );
		$started = microtime( true );
		$result = $provider->write( (int) $post_id, $target );
		$actual = ! is_wp_error( $result ) ? $provider->read( (int) $post_id ) : $target;
		if ( is_wp_error( $actual ) ) {
			$actual = $target;
		}
		$change_id = ! is_wp_error( $result ) ? self::record_change( (int) $post_id, $provider->get_id(), $existing, $actual ) : 0;
		$status = array(
			'provider'    => $provider->get_id(),
			'success'     => ! is_wp_error( $result ),
			'error_code'  => is_wp_error( $result ) ? $result->get_error_code() : '',
			'duration_ms' => (int) round( ( microtime( true ) - $started ) * 1000 ),
			'timestamp'   => time(),
			'change_id'   => $change_id,
		);
		update_option( self::OPTION_LAST_WRITE, $status, false );
		do_action( 'sftcy_wordai_seo_integration_event', 'write', $status );

		return $result;
	}

	private static function changes_table() {
		global $wpdb;
		return $wpdb->prefix . 'wordai_seo_changes';
	}

	private static function record_change( $post_id, $provider_id, array $before, array $after, $action_name = 'update' ) {
		if ( $before === $after ) {
			return 0;
		}

		global $wpdb;
		$result = $wpdb->insert(
			self::changes_table(),
			array(
				'change_uuid' => wp_generate_uuid4(),
				'post_id'     => (int) $post_id,
				'provider'    => sanitize_key( $provider_id ),
				'action_name' => sanitize_key( $action_name ),
				'before_json' => wp_json_encode( self::normalize_document( $before ) ),
				'after_json'  => wp_json_encode( self::normalize_document( $after ) ),
				'user_id'     => get_current_user_id(),
				'status'      => 'applied',
				'created_at'  => current_time( 'mysql', true ),
			),
			array( '%s', '%d', '%s', '%s', '%s', '%s', '%d', '%s', '%s' )
		);

		return false === $result ? 0 : (int) $wpdb->insert_id;
	}

	public static function latest_change_id( $post_id ) {
		global $wpdb;
		return (int) $wpdb->get_var(
			$wpdb->prepare(
				'SELECT id FROM ' . self::changes_table() . ' WHERE post_id = %d AND status = %s ORDER BY id DESC LIMIT 1',
				(int) $post_id,
				'applied'
			)
		);
	}

	public static function undo( $change_id ) {
		global $wpdb;
		$row = $wpdb->get_row(
			$wpdb->prepare( 'SELECT * FROM ' . self::changes_table() . ' WHERE id = %d AND status = %s', (int) $change_id, 'applied' ),
			ARRAY_A
		);
		if ( ! $row ) {
			return new WP_Error( 'wordai_seo_change_missing', __( 'The selected SEO change is no longer available to undo.', self::textdomain() ) );
		}

		$provider = self::provider();
		if ( ! $provider || $provider->get_id() !== $row['provider'] ) {
			return new WP_Error( 'wordai_seo_change_provider', __( 'Restore the SEO output owner used for this change before undoing it.', self::textdomain() ) );
		}

		$before = json_decode( $row['before_json'], true );
		if ( ! is_array( $before ) ) {
			return new WP_Error( 'wordai_seo_change_invalid', __( 'The saved SEO snapshot is invalid.', self::textdomain() ) );
		}

		$result = $provider->write( (int) $row['post_id'], self::normalize_document( $before ) );
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		$wpdb->update(
			self::changes_table(),
			array( 'status' => 'undone', 'undone_at' => current_time( 'mysql', true ) ),
			array( 'id' => (int) $row['id'] ),
			array( '%s', '%s' ),
			array( '%d' )
		);
		do_action( 'sftcy_wordai_seo_integration_event', 'undo', array( 'provider' => $provider->get_id(), 'success' => true, 'error_code' => '', 'duration_ms' => 0, 'timestamp' => time() ) );

		return (int) $row['post_id'];
	}

	public static function ajax_save_provider() {
		check_ajax_referer( self::NONCE_ACTION, 'security' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to change the SEO integration owner.', self::textdomain() ) ), 403 );
		}

		$provider_id = isset( $_POST['provider'] ) ? sanitize_key( wp_unslash( $_POST['provider'] ) ) : 'auto';
		$allowed = array_merge( array( 'auto' ), self::active_external_ids() );
		if ( ! in_array( $provider_id, $allowed, true ) ) {
			wp_send_json_error( array( 'message' => __( 'Choose an active supported SEO plugin.', self::textdomain() ) ), 400 );
		}

		update_option( self::OPTION_PROVIDER, $provider_id, false );
		wp_send_json_success(
			array(
				'message' => __( 'SEO output owner updated.', self::textdomain() ),
				'status'  => self::status(),
			)
		);
	}

	public static function render_admin_notice() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( ! $screen || false === strpos( (string) $screen->id, 'wordai' ) ) {
			return;
		}

		$error_key = 'sftcy_wordai_seo_save_error_' . get_current_user_id();
		$save_error = get_transient( $error_key );
		if ( $save_error ) {
			delete_transient( $error_key );
			echo '<div class="notice notice-error is-dismissible"><p><strong>' . esc_html__( 'WordAI could not save SEO fields.', self::textdomain() ) . '</strong> ' . esc_html( $save_error ) . '</p></div>';
		}

		if ( ! self::has_conflict() ) {
			return;
		}

		$url = admin_url( 'admin.php?page=sc-wordai-seo-scan' );
		echo '<div class="notice notice-error"><p><strong>' . esc_html__( 'WordAI SEO integration requires attention.', self::textdomain() ) . '</strong> ';
		echo esc_html__( 'Multiple supported SEO plugins are active. Automatic SEO writes are paused until you select one output owner.', self::textdomain() );
		echo ' <a href="' . esc_url( $url ) . '">' . esc_html__( 'Choose SEO owner', self::textdomain() ) . '</a></p></div>';
	}

	public static function normalize_document( array $document ) {
		$defaults = array(
			'provider'         => '',
			'provider_name'    => '',
			'provider_version' => '',
			'title'            => '',
			'description'      => '',
			'focus_keyword'    => '',
			'canonical'        => '',
			'robots'           => 'index,follow',
			'schema_type'      => '',
		);
		$document = wp_parse_args( $document, $defaults );
		$document['title']         = sanitize_text_field( $document['title'] );
		$document['description']   = sanitize_textarea_field( $document['description'] );
		$document['focus_keyword'] = sanitize_text_field( $document['focus_keyword'] );
		$document['canonical']     = esc_url_raw( $document['canonical'] );
		$document['schema_type']   = sanitize_text_field( $document['schema_type'] );
		$raw_robots                = strtolower( (string) $document['robots'] );
		$document['robots']        = false !== strpos( $raw_robots, 'noindex' ) ? 'noindex' : 'index';
		$document['robots']       .= false !== strpos( $raw_robots, 'nofollow' ) ? ',nofollow' : ',follow';

		return $document;
	}

	public static function filter_native_canonical( $canonical_url, $post ) {
		if ( ! self::should_wordai_output() || ! $post instanceof WP_Post ) {
			return $canonical_url;
		}
		$document = self::providers()['native']->read( $post->ID );
		return ! empty( $document['canonical'] ) ? $document['canonical'] : $canonical_url;
	}

	public static function filter_native_robots( array $robots ) {
		if ( ! self::should_wordai_output() || ! is_singular() ) {
			return $robots;
		}
		$document = self::providers()['native']->read( get_queried_object_id() );
		if ( false !== strpos( $document['robots'], 'noindex' ) ) {
			$robots['noindex'] = true;
			unset( $robots['index'] );
		} else {
			unset( $robots['noindex'] );
		}
		if ( false !== strpos( $document['robots'], 'nofollow' ) ) {
			$robots['nofollow'] = true;
			unset( $robots['follow'] );
		} else {
			unset( $robots['nofollow'] );
		}

		return $robots;
	}
}
