<?php

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

if ( class_exists( 'AIEO_SEO_Head', false ) ) {
	return;
}

class AIEO_SEO_Head {

	const CACHE_GROUP = 'aieo_seo';
	const CACHE_TTL   = HOUR_IN_SECONDS;

	
	private static $current = null;

	
	public static function table() {
		global $wpdb;
		return $wpdb->prefix . 'aieo_seo_head_cache';
	}

	
	public static function cache_key( $object_type, $object_id, $lang ) {
		return 'aieo_seo_head:' . $object_type . ':' . (int) $object_id . ':' . $lang;
	}

	
	public static function current_lang() {
		if ( defined( 'ICL_LANGUAGE_CODE' ) && ICL_LANGUAGE_CODE ) {
			return (string) ICL_LANGUAGE_CODE;
		}
		if ( function_exists( 'pll_current_language' ) ) {
			$pll = pll_current_language();
			if ( $pll ) {
				return (string) $pll;
			}
		}
		return '';
	}

	
	public static function get( $object_type, $object_id, $lang = null ) {
		$object_type = (string) $object_type;
		$object_id   = (int) $object_id;
		if ( '' === $object_type || $object_id <= 0 ) {
			return null;
		}
		if ( null === $lang ) {
			$lang = self::current_lang();
		}

		$key    = self::cache_key( $object_type, $object_id, $lang );
		$cached = wp_cache_get( $key, self::CACHE_GROUP );
		if ( false !== $cached ) {
			return is_array( $cached ) ? $cached : null;
		}

		global $wpdb;
		$t = self::table();
		
		
		
		$row = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT title, canonical, robots, head_html FROM `{$t}` WHERE object_type = %s AND object_id = %d AND lang = %s",
				$object_type,
				$object_id,
				$lang
			),
			ARRAY_A
		);

		wp_cache_set( $key, is_array( $row ) ? $row : '', self::CACHE_GROUP, self::CACHE_TTL );
		return is_array( $row ) ? $row : null;
	}

	
	public static function register() {
		
		
		
		static $done = false;
		if ( $done ) {
			return;
		}
		$done = true;
		if ( is_admin() ) {
			return;
		}
		if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
			return;
		}
		add_action( 'wp', array( __CLASS__, 'on_wp' ) );
	}

	
	public static function on_wp() {
		if ( is_admin() || is_feed() || is_embed() ) {
			return;
		}

		
		
		
		
		
		if ( self::competitor_active() ) {
			return;
		}

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

		
		
		
		
		
		if ( ( is_date() && self::archive_noindex( 'noindex_date' ) )
			|| ( is_author() && self::archive_noindex( 'noindex_author' ) ) ) {
			add_filter( 'wp_robots', array( __CLASS__, 'filter_robots_noindex_follow' ), 99 );
		}

		$resolved = self::resolve_current_object();
		if ( ! $resolved ) {
			self::maybe_paginated_robots_fallback();
			return;
		}
		list( $object_type, $object_id ) = $resolved;

		$row = self::get( $object_type, $object_id );
		if ( ! $row ) {
			self::maybe_paginated_robots_fallback();
			return;
		}
		self::$current = $row;

		if ( isset( $row['title'] ) && '' !== (string) $row['title'] ) {
			add_filter( 'pre_get_document_title', array( __CLASS__, 'filter_title' ), 99 );
			
			add_filter( 'document_title_parts', array( __CLASS__, 'filter_title_parts' ), 99 );
		}
		if ( isset( $row['robots'] ) && '' !== (string) $row['robots'] ) {
			add_filter( 'wp_robots', array( __CLASS__, 'filter_robots' ), 99 );
		} else {
			self::maybe_paginated_robots_fallback();
		}
		if ( isset( $row['canonical'] ) && '' !== (string) $row['canonical'] ) {
			
			remove_action( 'wp_head', 'rel_canonical' );
		}
		if ( isset( $row['head_html'] ) && '' !== (string) $row['head_html'] ) {
			add_action( 'wp_head', array( __CLASS__, 'emit_head' ), 1 );
		}

		
		
		
		
		
		
		add_filter( 'woocommerce_structured_data_type_for_page', array( __CLASS__, 'filter_wc_structured_data' ), 99 );
	}

	
	private static function competitor_active() {
		return defined( 'AIOSEO_VERSION' ) || class_exists( 'AIOSEO\\Plugin\\Common\\Main', false )
			|| defined( 'WPSEO_VERSION' ) || class_exists( 'WPSEO_Options', false )
			|| defined( 'RANK_MATH_VERSION' ) || class_exists( 'RankMath', false );
	}

	
	private static function engine_enabled() {
		$opt = get_option( 'aieo_dmm_settings' );
		return is_array( $opt ) && isset( $opt['seo']['enabled'] ) && ! empty( $opt['seo']['enabled'] );
	}

	
	private static function resolve_current_object() {
		if ( is_singular() ) {
			$id = (int) get_queried_object_id();
			if ( $id <= 0 ) {
				return null;
			}
			return array( (string) get_post_type( $id ), $id );
		}
		if ( is_category() || is_tag() || is_tax() ) {
			$term = get_queried_object();
			if ( $term instanceof WP_Term ) {
				return array( (string) $term->taxonomy, (int) $term->term_id );
			}
		}
		return null;
	}

	

	public static function filter_title( $title ) {
		return ( self::$current && ! empty( self::$current['title'] ) )
			? (string) self::$current['title']
			: $title;
	}

	public static function filter_title_parts( $parts ) {
		if ( self::$current && ! empty( self::$current['title'] ) ) {
			return array( 'title' => (string) self::$current['title'] );
		}
		return $parts;
	}

	
	public static function filter_robots( $robots ) {
		if ( ! self::$current || empty( self::$current['robots'] ) ) {
			return $robots;
		}
		$out = array();
		foreach ( explode( ',', (string) self::$current['robots'] ) as $token ) {
			$token = trim( $token );
			if ( '' === $token ) {
				continue;
			}
			if ( false !== strpos( $token, ':' ) ) {
				list( $k, $v ) = array_map( 'trim', explode( ':', $token, 2 ) );
				if ( '' !== $k ) {
					$out[ $k ] = $v;
				}
			} else {
				$out[ $token ] = true;
			}
		}
		
		
		
		
		if ( is_paged() ) {
			$pag = self::paginated_robots();
			if ( $pag['noindex'] ) {
				unset( $out['index'] );
				$out['noindex'] = true;
			}
			if ( $pag['nofollow'] ) {
				unset( $out['follow'] );
				$out['nofollow'] = true;
			}
		}
		return $out;
	}

	
	private static function paginated_robots() {
		$opt = get_option( 'aieo_dmm_settings' );
		$g   = ( is_array( $opt ) && isset( $opt['seo']['robots_global'] ) && is_array( $opt['seo']['robots_global'] ) )
			? $opt['seo']['robots_global'] : null;
		if ( null === $g ) {
			return array( 'noindex' => true, 'nofollow' => false );
		}
		return array(
			'noindex'  => ! empty( $g['noindex_paginated'] ),
			'nofollow' => ! empty( $g['nofollow_paginated'] ),
		);
	}

	
	private static function archive_noindex( $key ) {
		$opt = get_option( 'aieo_dmm_settings' );
		return is_array( $opt ) && ! empty( $opt['seo']['robots_global'][ $key ] );
	}

	
	private static function maybe_paginated_robots_fallback() {
		if ( ! is_paged() ) {
			return;
		}
		$pag = self::paginated_robots();
		if ( $pag['noindex'] || $pag['nofollow'] ) {
			add_filter( 'wp_robots', array( __CLASS__, 'filter_robots_paginated_fallback' ), 99 );
		}
	}

	
	public static function filter_robots_paginated_fallback( $robots ) {
		if ( ! is_array( $robots ) ) {
			$robots = array();
		}
		$pag = self::paginated_robots();
		if ( $pag['noindex'] ) {
			unset( $robots['index'] );
			$robots['noindex'] = true;
		}
		if ( $pag['nofollow'] ) {
			unset( $robots['follow'] );
			$robots['nofollow'] = true;
		}
		return $robots;
	}

	
	public static function filter_robots_noindex_follow( $robots ) {
		if ( ! is_array( $robots ) ) {
			$robots = array();
		}
		unset( $robots['index'] );
		$robots['noindex'] = true;
		$robots['follow']  = true;
		return $robots;
	}

	public static function emit_head() {
		if ( ! self::$current || empty( self::$current['head_html'] ) ) {
			return;
		}
		
		
		$html = (string) self::$current['head_html'];

		
		
		
		
		
		
		
		
		
		
		$n = self::current_page_num();
		if ( $n > 1 && ! empty( self::$current['canonical'] ) && self::canonical_is_own_url( (string) self::$current['canonical'] ) ) {
			$paged = self::paged_url( (string) self::$current['canonical'], $n );
			if ( '' !== $paged ) {
				$html = (string) preg_replace_callback(
					'#<link rel="canonical" href="[^"]*" ?/>#',
					static function () use ( $paged ) {
						return '<link rel="canonical" href="' . esc_url( $paged ) . '" />';
					},
					$html,
					1
				);
			}
		}

		echo "\n", $html, "\n"; 
	}

	
	private static function current_page_num() {
		return is_singular()
			? max( 1, (int) get_query_var( 'page' ) )
			: max( 1, (int) get_query_var( 'paged' ) );
	}

	
	private static function canonical_is_own_url( $canonical ) {
		$own = '';
		if ( is_singular() ) {
			$own = (string) get_permalink( get_queried_object_id() );
		} else {
			$term = get_queried_object();
			if ( $term instanceof WP_Term ) {
				$link = get_term_link( $term );
				$own  = is_wp_error( $link ) ? '' : (string) $link;
			}
		}
		return '' !== $own && untrailingslashit( $canonical ) === untrailingslashit( $own );
	}

	
	private static function paged_url( $canonical, $n ) {
		$canonical = trim( (string) $canonical );
		$n         = (int) $n;
		if ( '' === $canonical || $n <= 1 ) {
			return '';
		}
		if ( false !== strpos( $canonical, '?' ) ) {
			return add_query_arg( is_singular() ? 'page' : 'paged', $n, $canonical );
		}
		$base = trailingslashit( $canonical );
		if ( is_singular() && ! is_front_page() ) {
			return user_trailingslashit( $base . $n, 'single_paged' );
		}
		
		
		global $wp_rewrite;
		$pag_base = ( is_object( $wp_rewrite ) && ! empty( $wp_rewrite->pagination_base ) ) ? (string) $wp_rewrite->pagination_base : 'page';
		return user_trailingslashit( $base . $pag_base . '/' . $n, 'paged' );
	}

	
	public static function filter_wc_structured_data( $types ) {
		if ( ! is_array( $types ) ) {
			return $types;
		}
		
		
		
		return array_values( array_diff( $types, array( 'product', 'website', 'breadcrumblist' ) ) );
	}
}
