<?php
/** Provider readers for bounded global SEO settings. */

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

/** @param array<string,mixed> $settings @return array<string,mixed> */
function wpagent_seo_settings_payload( string $plugin, array $supported, array $settings ): array {
	$snapshot                  = wpagent_seo_settings_snapshot( $plugin );
	$unmapped_template_fields = array();
	foreach ( $supported as $index => $field ) {
		if ( ! str_ends_with( $field, '_template' ) || ! is_string( $settings[ $field ] ?? null ) ) {
			continue;
		}
		if ( null !== wpagent_seo_settings_provider_token( $plugin, $settings[ $field ] ) ) {
			$unmapped_template_fields[] = $field;
			unset( $supported[ $index ] );
		}
	}
	$supported = array_values( $supported );
	sort( $supported, SORT_STRING );
	sort( $unmapped_template_fields, SORT_STRING );
	return array(
		'plugin'                   => $plugin,
		'supported_fields'         => $supported,
		'unmapped_template_fields' => $unmapped_template_fields,
		'template_syntax'          => 'wpagently-v1',
		'template_tokens'          => wpagent_seo_settings_template_tokens(),
		'homepage_source'          => 'page' === get_option( 'show_on_front' ) && absint( get_option( 'page_on_front' ) ) > 0 ? 'static_page' : 'global',
		'settings'                 => $settings,
		'state_hash'               => wpagent_seo_settings_snapshot_hash( $plugin, $snapshot ),
	);
}

/** @param mixed $value */
function wpagent_seo_settings_toggle_on( $value ): bool {
	return true === $value || 1 === $value || '1' === $value || 'on' === $value || 'yes' === $value;
}

/** @param array<int|string,mixed> $robots */
function wpagent_seo_settings_robots_noindex( array $robots ): bool {
	return in_array( 'noindex', $robots, true );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_read_rankmath_seo_settings() {
	if ( ! class_exists( 'RankMath\Helper' ) ) {
		return new WP_Error( 'wpagent_seo_settings_provider_unavailable', __( 'Rank Math ist nicht vollständig geladen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$get = static function ( string $key, $default = '' ) {
		return \RankMath\Helper::get_settings( 'titles.' . $key, $default );
	};
	$author_robots = (array) $get( 'author_robots', array() );
	$date_robots   = (array) $get( 'date_archive_robots', array() );
	$author_custom = wpagent_seo_settings_toggle_on( $get( 'author_custom_robots', 'on' ) );
	$identity_type = 'person' === $get( 'knowledgegraph_type', 'person' ) ? 'person' : 'organization';
	$supported     = array(
		'title_separator', 'homepage_title_template', 'homepage_description_template',
		'author_archives_enabled', 'author_archives_noindex', 'author_archive_title_template', 'author_archive_description_template',
		'date_archives_enabled', 'date_archives_noindex', 'date_archive_title_template', 'date_archive_description_template',
		'search_noindex', 'search_title_template', 'identity_type', 'identity_name', 'identity_logo_url', 'website_name', 'alternate_website_name',
	);
	$settings = array(
		'title_separator'                    => wpagent_seo_separator_from_provider( (string) $get( 'title_separator', '-' ) ),
		'homepage_title_template'            => wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'homepage_title', '%sitename% %page% %sep% %sitedesc%' ) ),
		'homepage_description_template'      => wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'homepage_description', '' ) ),
		'author_archives_enabled'             => ! wpagent_seo_settings_toggle_on( $get( 'disable_author_archives', 'off' ) ),
		'author_archives_noindex'             => $author_custom && wpagent_seo_settings_robots_noindex( $author_robots ),
		'author_archive_title_template'      => wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'author_archive_title', '%name% %sep% %sitename% %page%' ) ),
		'author_archive_description_template'=> wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'author_archive_description', '' ) ),
		'date_archives_enabled'               => ! wpagent_seo_settings_toggle_on( $get( 'disable_date_archives', 'on' ) ),
		'date_archives_noindex'               => wpagent_seo_settings_robots_noindex( $date_robots ),
		'date_archive_title_template'        => wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'date_archive_title', '%date% %page% %sep% %sitename%' ) ),
		'date_archive_description_template'  => wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'date_archive_description', '' ) ),
		'search_noindex'                     => wpagent_seo_settings_toggle_on( $get( 'noindex_search', 'on' ) ),
		'search_title_template'               => wpagent_seo_settings_template_from_provider( 'rankmath', (string) $get( 'search_title', '%search_query% %page% %sep% %sitename%' ) ),
		'identity_type'                       => $identity_type,
		'identity_name'                       => (string) $get( 'knowledgegraph_name', get_bloginfo( 'name' ) ),
		'identity_logo_url'                   => (string) $get( 'knowledgegraph_logo', '' ),
		'website_name'                        => (string) $get( 'website_name', get_bloginfo( 'name' ) ),
		'alternate_website_name'              => (string) $get( 'website_alternate_name', '' ),
	);
	return wpagent_seo_settings_payload( 'rankmath', $supported, $settings );
}

/** @return array<string,string> */
function wpagent_yoast_separator_map(): array {
	return array(
		'sc-dash' => '-', 'sc-ndash' => '–', 'sc-mdash' => '—', 'sc-colon' => ':', 'sc-middot' => '·',
		'sc-bull' => '•', 'sc-star' => '*', 'sc-smstar' => '⋆', 'sc-pipe' => '|', 'sc-tilde' => '~',
		'sc-laquo' => '«', 'sc-raquo' => '»', 'sc-lt' => '>', 'sc-gt' => '<',
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_read_yoast_seo_settings() {
	if ( ! class_exists( 'WPSEO_Options' ) ) {
		return new WP_Error( 'wpagent_seo_settings_provider_unavailable', __( 'Yoast SEO ist nicht vollständig geladen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	WPSEO_Options::clear_cache();
	$get            = static fn( string $key, $default = '' ) => WPSEO_Options::get( $key, $default, array( 'wpseo_titles' ) );
	$separator_map  = wpagent_yoast_separator_map();
	$separator_key  = (string) $get( 'separator', 'sc-dash' );
	$identity_type  = 'person' === $get( 'company_or_person', 'company' ) ? 'person' : 'organization';
	$identity_name  = 'person' === $identity_type ? (string) $get( 'person_name', '' ) : (string) $get( 'company_name', '' );
	$identity_logo  = 'person' === $identity_type ? (string) $get( 'person_logo', '' ) : (string) $get( 'company_logo', '' );
	$supported      = array(
		'title_separator', 'homepage_title_template', 'homepage_description_template',
		'author_archives_enabled', 'author_archives_noindex', 'author_archive_title_template', 'author_archive_description_template',
		'date_archives_enabled', 'date_archives_noindex', 'date_archive_title_template', 'date_archive_description_template',
		'search_title_template', 'identity_type', 'identity_name', 'identity_logo_url', 'website_name', 'alternate_website_name',
	);
	$settings = array(
		'title_separator'                    => $separator_map[ $separator_key ] ?? '-',
		'homepage_title_template'            => wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'title-home-wpseo', '' ) ),
		'homepage_description_template'      => wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'metadesc-home-wpseo', '' ) ),
		'author_archives_enabled'             => ! (bool) $get( 'disable-author', false ),
		'author_archives_noindex'             => (bool) $get( 'noindex-author-wpseo', false ),
		'author_archive_title_template'      => wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'title-author-wpseo', '' ) ),
		'author_archive_description_template'=> wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'metadesc-author-wpseo', '' ) ),
		'date_archives_enabled'               => ! (bool) $get( 'disable-date', false ),
		'date_archives_noindex'               => (bool) $get( 'noindex-archive-wpseo', true ),
		'date_archive_title_template'        => wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'title-archive-wpseo', '' ) ),
		'date_archive_description_template'  => wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'metadesc-archive-wpseo', '' ) ),
		'search_title_template'               => wpagent_seo_settings_template_from_provider( 'yoast', (string) $get( 'title-search-wpseo', '' ) ),
		'identity_type'                       => $identity_type,
		'identity_name'                       => $identity_name,
		'identity_logo_url'                   => $identity_logo,
		'website_name'                        => (string) $get( 'website_name', '' ),
		'alternate_website_name'              => (string) $get( 'alternate_website_name', '' ),
	);
	return wpagent_seo_settings_payload( 'yoast', $supported, $settings );
}

function wpagent_aioseo_settings_valid_text( $value, bool $nullable = false ): bool {
	if ( null === $value ) {
		return $nullable;
	}
	if ( ! is_string( $value ) || ! wp_is_valid_utf8( $value ) ) {
		return false;
	}
	$length = function_exists( 'mb_strlen' ) ? mb_strlen( $value, 'UTF-8' ) : strlen( $value );
	return $length <= 4096
		&& ! preg_match( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', $value )
		&& false === strpos( $value, "\r" )
		&& false === strpos( $value, "\n" )
		&& wp_strip_all_tags( $value ) === $value
		&& trim( $value ) === $value;
}

/** @return array{global:array<string,mixed>,schema:array<string,mixed>,archives:array<string,mixed>,global_robots:array<string,mixed>}|WP_Error */
function wpagent_aioseo_settings_tree() {
	if ( ! function_exists( 'aioseo' ) ) {
		return new WP_Error( 'wpagent_seo_settings_provider_unavailable', __( 'AIOSEO ist nicht vollständig geladen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}

	try {
		$provider        = aioseo();
		$options_service = is_object( $provider ) && isset( $provider->options ) ? $provider->options : null;
		if ( ! is_object( $options_service ) || ! is_callable( array( $options_service, 'noConflict' ) ) ) {
			return new WP_Error( 'wpagent_seo_settings_provider_unavailable', __( 'AIOSEO ist nicht vollständig geladen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$isolated = $options_service->noConflict();
		if ( ! is_object( $isolated ) || $isolated === $options_service || ! is_callable( array( $isolated, 'all' ) ) ) {
			throw new RuntimeException( 'AIOSEO options proxy is incompatible.' );
		}
		$options = $isolated->all();
	} catch ( Throwable ) {
		return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'AIOSEO konnte seine globalen Einstellungen nicht bereitstellen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}

	$search_appearance = is_array( $options ) ? ( $options['searchAppearance'] ?? null ) : null;
	$global            = is_array( $search_appearance ) ? ( $search_appearance['global'] ?? null ) : null;
	$schema            = is_array( $global ) ? ( $global['schema'] ?? null ) : null;
	$archives          = is_array( $search_appearance ) ? ( $search_appearance['archives'] ?? null ) : null;
	$advanced          = is_array( $search_appearance ) ? ( $search_appearance['advanced'] ?? null ) : null;
	$global_robots     = is_array( $advanced ) ? ( $advanced['globalRobotsMeta'] ?? null ) : null;
	if ( ! is_array( $global ) || ! is_array( $schema ) || ! is_array( $archives ) || ! is_array( $global_robots ) ) {
		return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}

	$required_global = array( 'separator', 'siteTitle', 'metaDescription' );
	$required_schema = array( 'siteRepresents', 'personName', 'organizationName', 'personLogo', 'organizationLogo', 'websiteName', 'websiteAlternateName' );
	foreach ( $required_global as $key ) {
		if ( ! array_key_exists( $key, $global ) ) {
			return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	foreach ( $required_schema as $key ) {
		if ( ! array_key_exists( $key, $schema ) ) {
			return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	foreach ( $required_global as $key ) {
		if ( ! wpagent_aioseo_settings_valid_text( $global[ $key ] ) ) {
			return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	if ( ! in_array( $global['separator'], array_values( wpagent_seo_separator_entities() ), true ) ) {
		return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( ! in_array( $schema['siteRepresents'], array( 'person', 'organization' ), true ) ) {
		return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	foreach ( array( 'personName', 'organizationName', 'personLogo', 'organizationLogo', 'websiteName', 'websiteAlternateName' ) as $key ) {
		if ( ! wpagent_aioseo_settings_valid_text( $schema[ $key ], true ) ) {
			return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	if (
		! array_key_exists( 'default', $global_robots ) ||
		! array_key_exists( 'noindex', $global_robots ) ||
		! is_bool( $global_robots['default'] ) ||
		! is_bool( $global_robots['noindex'] )
	) {
		return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	foreach ( array( 'author', 'date', 'search' ) as $archive ) {
		$config = $archives[ $archive ] ?? null;
		$robots = is_array( $config ) && is_array( $config['advanced'] ?? null ) ? ( $config['advanced']['robotsMeta'] ?? null ) : null;
		if (
			! is_array( $config ) ||
			! is_array( $robots ) ||
			! array_key_exists( 'show', $config ) ||
			! array_key_exists( 'title', $config ) ||
			! array_key_exists( 'metaDescription', $config ) ||
			! array_key_exists( 'default', $robots ) ||
			! array_key_exists( 'noindex', $robots ) ||
			! is_bool( $config['show'] ) ||
			! wpagent_aioseo_settings_valid_text( $config['title'], true ) ||
			! wpagent_aioseo_settings_valid_text( $config['metaDescription'], true ) ||
			! is_bool( $robots['default'] ) ||
			! is_bool( $robots['noindex'] )
		) {
			return new WP_Error( 'wpagent_aioseo_settings_incompatible', __( 'Die Struktur der globalen AIOSEO-Einstellungen wird von dieser wpagently-Version nicht unterstützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}

	return array(
		'global'   => $global,
		'schema'   => $schema,
		'archives' => $archives,
		'global_robots' => $global_robots,
	);
}

/** @param array<string,mixed> $archives @param array<string,mixed> $global_robots */
function wpagent_aioseo_archive_noindex( array $archives, array $global_robots, string $archive ): bool {
	$config = $archives[ $archive ];
	$robots = $config['advanced']['robotsMeta'];
	if ( ! $config['show'] ) {
		return true;
	}
	if ( ! $robots['default'] ) {
		return $robots['noindex'];
	}
	return ! $global_robots['default'] && $global_robots['noindex'];
}

/** @return array<string,mixed>|WP_Error */
function wpagent_read_aioseo_seo_settings() {
	$tree = wpagent_aioseo_settings_tree();
	if ( is_wp_error( $tree ) ) {
		return $tree;
	}
	$global        = $tree['global'];
	$schema        = $tree['schema'];
	$archives      = $tree['archives'];
	$global_robots = $tree['global_robots'];
	$identity_type = 'person' === (string) $schema['siteRepresents'] ? 'person' : 'organization';
	$identity_name = 'person' === $identity_type ? (string) $schema['personName'] : (string) $schema['organizationName'];
	$identity_logo = 'person' === $identity_type ? (string) $schema['personLogo'] : (string) $schema['organizationLogo'];
	$supported     = array(
		'title_separator', 'homepage_title_template', 'homepage_description_template',
		'author_archives_noindex', 'author_archive_title_template', 'author_archive_description_template',
		'date_archives_noindex', 'date_archive_title_template', 'date_archive_description_template',
		'search_noindex', 'search_title_template', 'search_description_template',
		'identity_type', 'identity_name', 'identity_logo_url', 'website_name', 'alternate_website_name',
	);
	$settings = array(
		'title_separator'                    => wpagent_seo_separator_from_provider( (string) $global['separator'] ),
		'homepage_title_template'            => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $global['siteTitle'] ),
		'homepage_description_template'      => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $global['metaDescription'] ),
		'author_archives_noindex'             => wpagent_aioseo_archive_noindex( $archives, $global_robots, 'author' ),
		'author_archive_title_template'      => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $archives['author']['title'] ),
		'author_archive_description_template'=> wpagent_seo_settings_template_from_provider( 'aioseo', (string) $archives['author']['metaDescription'] ),
		'date_archives_noindex'               => wpagent_aioseo_archive_noindex( $archives, $global_robots, 'date' ),
		'date_archive_title_template'        => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $archives['date']['title'] ),
		'date_archive_description_template'  => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $archives['date']['metaDescription'] ),
		'search_noindex'                      => wpagent_aioseo_archive_noindex( $archives, $global_robots, 'search' ),
		'search_title_template'               => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $archives['search']['title'] ),
		'search_description_template'         => wpagent_seo_settings_template_from_provider( 'aioseo', (string) $archives['search']['metaDescription'] ),
		'identity_type'                       => $identity_type,
		'identity_name'                       => $identity_name,
		'identity_logo_url'                   => $identity_logo,
		'website_name'                        => (string) $schema['websiteName'],
		'alternate_website_name'              => (string) $schema['websiteAlternateName'],
	);
	return wpagent_seo_settings_payload( 'aioseo', $supported, $settings );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_read_seopress_seo_settings() {
	if ( ! function_exists( 'seopress_get_service' ) ) {
		return new WP_Error( 'wpagent_seo_settings_provider_unavailable', __( 'SEOPress ist nicht vollständig geladen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$titles     = get_option( 'seopress_titles_option_name', array() );
	$social     = get_option( 'seopress_social_option_name', array() );
	$titles     = is_array( $titles ) ? $titles : array();
	$social     = is_array( $social ) ? $social : array();
	$type       = strtolower( (string) ( $social['seopress_social_knowledge_type'] ?? '' ) );
	$supported  = array(
		'title_separator', 'homepage_title_template', 'homepage_description_template',
		'author_archives_noindex', 'author_archive_title_template', 'author_archive_description_template',
		'date_archives_noindex', 'date_archive_title_template', 'date_archive_description_template',
		'search_noindex', 'search_title_template', 'search_description_template',
		'identity_type', 'identity_name', 'identity_logo_url',
	);
	$settings = array(
		'title_separator'                    => (string) ( $titles['seopress_titles_sep'] ?? '-' ),
		'homepage_title_template'            => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_home_site_title'] ?? '' ) ),
		'homepage_description_template'      => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_home_site_desc'] ?? '' ) ),
		'author_archives_noindex'             => wpagent_seo_settings_toggle_on( $titles['seopress_titles_archives_author_noindex'] ?? '' ),
		'author_archive_title_template'      => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_archives_author_title'] ?? '' ) ),
		'author_archive_description_template'=> wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_archives_author_desc'] ?? '' ) ),
		'date_archives_noindex'               => wpagent_seo_settings_toggle_on( $titles['seopress_titles_archives_date_noindex'] ?? '' ),
		'date_archive_title_template'        => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_archives_date_title'] ?? '' ) ),
		'date_archive_description_template'  => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_archives_date_desc'] ?? '' ) ),
		'search_noindex'                      => wpagent_seo_settings_toggle_on( $titles['seopress_titles_archives_search_title_noindex'] ?? '' ),
		'search_title_template'               => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_archives_search_title'] ?? '' ) ),
		'search_description_template'         => wpagent_seo_settings_template_from_provider( 'seopress', (string) ( $titles['seopress_titles_archives_search_desc'] ?? '' ) ),
		'identity_type'                       => 'person' === $type ? 'person' : ( 'organization' === $type ? 'organization' : null ),
		'identity_name'                       => (string) ( $social['seopress_social_knowledge_name'] ?? '' ),
		'identity_logo_url'                   => (string) ( $social['seopress_social_knowledge_img'] ?? '' ),
	);
	return wpagent_seo_settings_payload( 'seopress', $supported, $settings );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_read_seo_settings( string $plugin ) {
	$readers = array(
		'rankmath' => 'wpagent_read_rankmath_seo_settings',
		'yoast'    => 'wpagent_read_yoast_seo_settings',
		'aioseo'   => 'wpagent_read_aioseo_seo_settings',
		'seopress' => 'wpagent_read_seopress_seo_settings',
	);
	if ( ! isset( $readers[ $plugin ] ) ) {
		return new WP_Error( 'wpagent_seo_plugin_missing', __( 'Kein unterstütztes SEO-Plugin aktiv.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return call_user_func( $readers[ $plugin ] );
}
