<?php
/**
 * View-model builder for the General > Schema settings tab (V2).
 *
 * @package SEOvaultSEO\Admin
 */

namespace SEOvaultSEO\Admin;

use SEOvaultSEO\Core\Options;
use SEOvaultSEO\Schema\SchemaArchitectureSettings;
use SEOvaultSEO\Schema\SchemaCompatibilityPolicy;
use SEOvaultSEO\Schema\SchemaExtensionApi;
use SEOvaultSEO\Schema\SchemaLegacyGlobalDeprecation;
use SEOvaultSEO\Schema\SchemaTypePolicyRegistry;
use SEOvaultSEO\Schema\SchemaMigration;
use SEOvaultSEO\Schema\Validation\RuleSetVersion;
use SEOvaultSEO\WooCommerce\WooCommerce;

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

/**
 * Presents section data for the V2 Schema tab without echoing HTML.
 */
class SchemaSettingsTabPresenter {

	/**
	 * Documentation URL for Schema settings help (allowlisted host).
	 */
	const DOCS_URL = 'https://www.seovaultai.com/docs/schema';

	/**
	 * Build the full V2 tab view model.
	 *
	 * @return array
	 */
	public function present() {
		$woo_active = WooCommerce::is_woocommerce_active();
		$settings   = SchemaArchitectureSettings::get_v2_settings_snapshot();

		return array(
			'output'     => $this->present_output_section( $settings ),
			'automatic'  => $this->present_automatic_section( $woo_active, $settings ),
			'additional' => $this->present_additional_section( $woo_active, $settings ),
			'templates'  => $this->present_templates_section(),
			'advanced'   => $this->present_advanced_section(),
			'migration'  => $this->present_migration_banner(),
			'settings'   => $settings,
		);
	}

	/**
	 * Schema output section.
	 *
	 * @param array|null $settings Optional V2 settings snapshot.
	 * @return array
	 */
	public function present_output_section( $settings = null ) {
		if ( ! is_array( $settings ) ) {
			$settings = SchemaArchitectureSettings::get_v2_settings_snapshot();
		}
		$enabled     = ( 'yes' === ( $settings['schema_enabled'] ?? 'yes' ) );
		$compat      = SchemaCompatibilityPolicy::get_status();
		$competitors = isset( $compat['competitors'] ) && is_array( $compat['competitors'] ) ? $compat['competitors'] : array();

		$status_label = $enabled
			? __( 'Structured data output is on', 'seovault-ai' )
			: __( 'Structured data output is off', 'seovault-ai' );

		$compatibility = isset( $compat['recommendation'] ) ? (string) $compat['recommendation'] : '';
		if ( '' === $compatibility ) {
			$compatibility = __( 'SEOvault manages schema output for this site.', 'seovault-ai' );
		}

		return array(
			'title'            => __( 'Schema output', 'seovault-ai' ),
			'enabled'          => $enabled,
			'status_label'     => $status_label,
			'explanation'      => __( 'SEOvault adds basic schema automatically from your site and page context. You do not need to enable every Schema.org type.', 'seovault-ai' ),
			'compatibility'    => $compatibility,
			'competitors'      => $competitors,
			'duplicate_risk'   => isset( $compat['duplicate_risk'] ) ? (string) $compat['duplicate_risk'] : 'none',
			'output_mode'      => isset( $compat['output_mode'] ) ? (string) $compat['output_mode'] : Options::get_output_mode(),
			'rewrites_third_party' => false,
			'docs_url'         => self::DOCS_URL,
			'docs_label'       => __( 'Learn about schema in SEOvault', 'seovault-ai' ),
			'toggle_label'     => __( 'Output structured data (JSON-LD)', 'seovault-ai' ),
		);
	}

	/**
	 * Automatic / foundational schema rows.
	 *
	 * @param bool       $woo_active Whether WooCommerce is active.
	 * @param array|null $settings   Optional V2 settings snapshot.
	 * @return array
	 */
	public function present_automatic_section( $woo_active = null, $settings = null ) {
		if ( null === $woo_active ) {
			$woo_active = WooCommerce::is_woocommerce_active();
		}
		if ( ! is_array( $settings ) ) {
			$settings = SchemaArchitectureSettings::get_v2_settings_snapshot();
		}

		$identity  = isset( $settings['publisher_identity'] ) ? (string) $settings['publisher_identity'] : SchemaArchitectureSettings::get_publisher_identity();
		$automatic = isset( $settings['automatic'] ) && is_array( $settings['automatic'] )
			? $settings['automatic']
			: SchemaArchitectureSettings::get_automatic_components();
		$rows      = array(
			array(
				'id'             => 'website_page',
				'label'          => __( 'Website and page information', 'seovault-ai' ),
				'when'           => __( 'Added on public pages from your site URL and page context.', 'seovault-ai' ),
				'settings_url'   => admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-homepage' ),
				'settings_label' => __( 'Homepage settings', 'seovault-ai' ),
				'toggle'         => null,
			),
			array(
				'id'             => 'site_identity',
				'label'          => __( 'Site identity', 'seovault-ai' ),
				'when'           => sprintf(
					/* translators: %s: Organization or Person. */
					__( 'Publishes your site as %s using the identity setting below.', 'seovault-ai' ),
					'person' === $identity ? __( 'a Person', 'seovault-ai' ) : ( 'both' === $identity ? __( 'an Organization and a Person', 'seovault-ai' ) : __( 'an Organization', 'seovault-ai' ) )
				),
				'settings_url'   => admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-local-seo' ),
				'settings_label' => __( 'Identity / Local SEO', 'seovault-ai' ),
				'toggle'         => null,
			),
			array(
				'id'             => 'article',
				'label'          => __( 'Article information', 'seovault-ai' ),
				'when'           => __( 'Added for eligible posts and articles automatically.', 'seovault-ai' ),
				'settings_url'   => admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-templates' ),
				'settings_label' => __( 'Content templates', 'seovault-ai' ),
				'toggle'         => null,
			),
			array(
				'id'             => 'breadcrumbs',
				'label'          => __( 'Breadcrumbs', 'seovault-ai' ),
				'when'           => __( 'Added only when SEOvault can build a valid breadcrumb trail.', 'seovault-ai' ),
				'settings_url'   => admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-breadcrumbs' ),
				'settings_label' => __( 'Breadcrumb settings', 'seovault-ai' ),
				'toggle'         => array(
					'key'     => 'breadcrumbs',
					'enabled' => ! empty( $automatic['breadcrumbs'] ),
					'label'   => __( 'Include breadcrumb schema when available', 'seovault-ai' ),
				),
			),
			array(
				'id'             => 'search_action',
				'label'          => __( 'Site search action', 'seovault-ai' ),
				'when'           => __( 'Added only when a working site search URL can be generated.', 'seovault-ai' ),
				'settings_url'   => admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-homepage' ),
				'settings_label' => __( 'Site search settings', 'seovault-ai' ),
				'toggle'         => array(
					'key'     => 'search_action',
					'enabled' => ! empty( $automatic['search_action'] ),
					'label'   => __( 'Include site search action when available', 'seovault-ai' ),
				),
			),
		);

		if ( $woo_active ) {
			$rows[] = array(
				'id'             => 'woocommerce_products',
				'label'          => __( 'WooCommerce products', 'seovault-ai' ),
				'when'           => __( 'Product schema is generated automatically for real WooCommerce products when the data is complete.', 'seovault-ai' ),
				'settings_url'   => admin_url( 'admin.php?page=seovault-ai-general&tab=vtab-woocommerce' ),
				'settings_label' => __( 'WooCommerce SEO', 'seovault-ai' ),
				'toggle'         => null,
			);
		}

		return array(
			'title'              => __( 'Automatic schema', 'seovault-ai' ),
			'intro'              => __( 'These items appear when the page context supports them. They are not “enable this type on every page” switches.', 'seovault-ai' ),
			'rows'               => $rows,
			'woo_active'         => (bool) $woo_active,
			'woo_inactive_note'  => $woo_active
				? ''
				: __( 'WooCommerce is not active, so automatic Product schema is not listed here.', 'seovault-ai' ),
			'publisher_identity' => $identity,
			'identity_label'     => __( 'Publisher identity for automatic schema', 'seovault-ai' ),
			'identity_options'   => array(
				'organization' => __( 'Organization', 'seovault-ai' ),
				'person'       => __( 'Person', 'seovault-ai' ),
				'both'         => __( 'Organization and Person', 'seovault-ai' ),
			),
			'automatic'          => $automatic,
		);
	}

	/**
	 * Additional specialized type catalogue (no global enable checkboxes).
	 *
	 * @param bool       $woo_active Whether WooCommerce is active.
	 * @param array|null $settings   Optional V2 settings snapshot.
	 * @return array
	 */
	public function present_additional_section( $woo_active = null, $settings = null ) {
		if ( null === $woo_active ) {
			$woo_active = WooCommerce::is_woocommerce_active();
		}
		if ( ! is_array( $settings ) ) {
			$settings = SchemaArchitectureSettings::get_v2_settings_snapshot();
		}
		$catalogue       = isset( $settings['catalogue'] ) && is_array( $settings['catalogue'] )
			? $settings['catalogue']
			: SchemaArchitectureSettings::get_catalogue_presentation();
		$show_extensions = ! isset( $catalogue['show_extension_types'] ) || ! empty( $catalogue['show_extension_types'] );

		$preferred = array(
			'FAQPage',
			'HowTo',
			'Recipe',
			'Event',
			'Course',
			'JobPosting',
			'SoftwareApplication',
			'Review',
		);

		$items = array();
		foreach ( $preferred as $type ) {
			$entry = SchemaTypePolicyRegistry::get_entry( $type );
			if ( ! is_array( $entry ) ) {
				continue;
			}
			$items[] = $this->present_additional_item( $entry );
		}

		// Product manual fallback only when commerce integration does not own it.
		if ( ! $woo_active ) {
			$product = SchemaTypePolicyRegistry::get_entry( 'Product' );
			if ( is_array( $product ) ) {
				$item                 = $this->present_additional_item( $product );
				$item['fallback']     = true;
				$item['availability'] = __( 'Manual Product markup is available only because no commerce integration owns product pages. Prefer a commerce integration when possible.', 'seovault-ai' );
				$items[]              = $item;
			}
		}

		// Extension / filtered specialized types not already listed.
		$listed = array();
		foreach ( $items as $item ) {
			$listed[ $item['type'] ] = true;
		}
		if ( $show_extensions ) {
			foreach ( SchemaTypePolicyRegistry::get_entries() as $type => $entry ) {
				if ( isset( $listed[ $type ] ) ) {
					continue;
				}
				if ( ! SchemaTypePolicyRegistry::is_specialized( $type ) ) {
					continue;
				}
				if ( 'Product' === $type && $woo_active ) {
					continue;
				}
				$item              = $this->present_additional_item( $entry );
				$item['extension'] = true;
				$items[]           = $item;
			}
		}

		return array(
			'title'                      => __( 'Additional schema types', 'seovault-ai' ),
			'intro'                      => __( 'Add these only when the content really exists. Availability here does not publish the type site-wide.', 'seovault-ai' ),
			'items'                      => $items,
			'show_extension_types'       => $show_extensions,
			'show_extension_types_label' => __( 'Show extension schema types in this catalogue', 'seovault-ai' ),
			'catalogue'                  => $catalogue,
		);
	}

	/**
	 * One additional-type catalogue row.
	 *
	 * @param array $entry Policy entry.
	 * @return array
	 */
	private function present_additional_item( array $entry ) {
		$type   = (string) ( $entry['type'] ?? '' );
		$label  = (string) ( $entry['label'] ?? $type );
		$method = (string) ( $entry['editor_method'] ?? '' );

		$how = __( 'Add this from an individual post, a visible SEOvault block, or a targeted template.', 'seovault-ai' );
		if ( 'block' === $method ) {
			$how = __( 'Insert the matching SEOvault block in the post editor. Incomplete blocks stay unpublished until ready.', 'seovault-ai' );
		} elseif ( 'guided_form' === $method ) {
			$how = __( 'Open Add schema on a post and fill the guided form, or create a narrowly targeted template.', 'seovault-ai' );
		} elseif ( 'integration' === $method ) {
			$how = __( 'Generated by an integration when the product or entity data is complete.', 'seovault-ai' );
		}

		return array(
			'type'           => $type,
			'label'          => $label,
			'category'       => (string) ( $entry['category'] ?? '' ),
			'editor_method'  => $method,
			'availability'   => __( 'Add this to an individual post, a visible SEOvault block, or a targeted template. Availability does not publish it site-wide.', 'seovault-ai' ),
			'how'            => $how,
			'learn_url'      => self::DOCS_URL,
			'learn_label'    => __( 'Learn how', 'seovault-ai' ),
			'template_url'   => admin_url( 'edit.php?post_type=seovault_schema' ),
			'template_label' => __( 'Create template', 'seovault-ai' ),
			'posts_url'      => admin_url( 'edit.php' ),
			'posts_label'    => __( 'View posts', 'seovault-ai' ),
			'fallback'       => false,
			'extension'      => false,
		);
	}

	/**
	 * Templates section summary.
	 *
	 * @return array
	 */
	public function present_templates_section() {
		$counts    = wp_count_posts( 'seovault_schema' );
		$published = isset( $counts->publish ) ? (int) $counts->publish : 0;
		$drafts    = isset( $counts->draft ) ? (int) $counts->draft : 0;

		return array(
			'title'        => __( 'Templates', 'seovault-ai' ),
			'intro'        => __( 'Reusable templates must use narrow display conditions and pass readiness before they publish. Incomplete templates can stay as drafts.', 'seovault-ai' ),
			'published'    => $published,
			'drafts'       => $drafts,
			'manage_url'   => admin_url( 'edit.php?post_type=seovault_schema' ),
			'manage_label' => __( 'Manage schema templates', 'seovault-ai' ),
			'create_url'   => admin_url( 'post-new.php?post_type=seovault_schema' ),
			'create_label' => __( 'Create template', 'seovault-ai' ),
			'constraint'   => __( 'Templates must not silently default to all posts.', 'seovault-ai' ),
		);
	}

	/**
	 * Advanced section (ruleset, custom JSON, migration, hooks).
	 *
	 * @return array
	 */
	public function present_advanced_section() {
		$restore     = SchemaMigration::is_restore_available();
		$deprecation = SchemaLegacyGlobalDeprecation::analyze();
		$hook_names  = SchemaExtensionApi::documented_filter_names();

		return array(
			'title'             => __( 'Advanced', 'seovault-ai' ),
			'ruleset_version'   => RuleSetVersion::get_current(),
			'ruleset_label'     => __( 'Local Schema Health ruleset', 'seovault-ai' ),
			'custom_json_title' => __( 'Custom JSON-LD', 'seovault-ai' ),
			'custom_json_text'  => __( 'Custom JSON on a post is an advanced escape hatch. It can add to or replace automatic schema for that post only — it is not a site-wide type switch.', 'seovault-ai' ),
			'hooks_title'       => __( 'Extension hooks', 'seovault-ai' ),
			'hooks_text'        => __( 'Developers can register type policy, readiness, sanitizer allow-lists, presentation strings, and extension contributors through documented filters. Extension types appear in Additional schema types when registered. Extensions must tag source as extension and cannot bypass readiness or claim trusted-integration status.', 'seovault-ai' ),
			'hooks_list'        => $hook_names,
			'migration_title'   => __( 'Migration backup and restore', 'seovault-ai' ),
			'migration_text'    => $restore
				? __( 'A verified migration backup is available. Use the migration review screen to restore the previous configuration if needed.', 'seovault-ai' )
				: __( 'No migration restore window is open right now.', 'seovault-ai' ),
			'migration_url'     => SchemaMigrationAdmin::review_url(),
			'migration_label'   => __( 'Open migration review', 'seovault-ai' ),
			'restore_available' => $restore,
			'show_legacy_link'  => $restore || SchemaMigration::should_show_notice() || ! empty( $deprecation['has_deprecated'] ),
			'legacy_note'       => __( 'Legacy global type checkboxes are not part of the normal Schema settings. Use migration review or rollback if you need the previous configuration.', 'seovault-ai' ),
		);
	}

	/**
	 * Optional inline migration banner for the Schema tab.
	 *
	 * @return array
	 */
	public function present_migration_banner() {
		$show = SchemaMigration::should_show_notice();

		return array(
			'show'         => $show,
			'title'        => __( 'Schema setup was updated', 'seovault-ai' ),
			'message'      => __( 'Older versions could apply optional schema such as Recipe, Event, and Course to ordinary posts. SEOvault now uses safer automatic defaults and preserved your previous configuration.', 'seovault-ai' ),
			'review_url'   => SchemaMigrationAdmin::review_url(),
			'review_label' => __( 'Review converted drafts/templates', 'seovault-ai' ),
		);
	}
}
