<?php
/**
 * SEO Foundation Module
 *
 * Provides Open Graph, Twitter Cards, canonical, and Schema hooks.
 * Does not replace dedicated SEO plugins — complements them when enabled.
 *
 * @package Kutby
 * @since   1.0.0
 */

declare(strict_types=1);

namespace Kutby\SEO;

use Kutby\Contracts\ModuleInterface;
use Kutby\ThemeOptions\Manager;

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

/**
 * Class SEO
 */
final class SEO implements ModuleInterface {

	/**
	 * Register hooks.
	 *
	 * @return void
	 */
	public function register(): void {
		add_action( 'wp_head', array( $this, 'output' ), 5 );
	}

	/**
	 * {@inheritdoc}
	 */
	public function boot(): void {}

	/**
	 * Output SEO meta based on options.
	 *
	 * @return void
	 */
	public function output(): void {
		if ( is_admin() ) {
			return;
		}

		// Bail if a major SEO plugin is active (avoid duplicate tags).
		if ( $this->has_seo_plugin() ) {
			return;
		}

		$opts = Manager::get_group( 'seo' );

		if ( ! empty( $opts['canonical'] ) ) {
			$this->canonical();
		}

		if ( ! empty( $opts['open_graph'] ) ) {
			$this->open_graph();
		}

		if ( ! empty( $opts['twitter_cards'] ) ) {
			$this->twitter_cards();
		}

		if ( ! empty( $opts['schema'] ) ) {
			$this->schema_organization();
		}
	}

	/**
	 * Detect popular SEO plugins.
	 *
	 * @return bool
	 */
	private function has_seo_plugin(): bool {
		return defined( 'WPSEO_VERSION' )
			|| defined( 'RANK_MATH_VERSION' )
			|| defined( 'AIOSEO_VERSION' )
			|| class_exists( 'The_SEO_Framework\\Load', false );
	}

	/**
	 * Print canonical link.
	 *
	 * @return void
	 */
	private function canonical(): void {
		$url = $this->current_url();
		if ( ! $url ) {
			return;
		}

		printf( '<link rel="canonical" href="%s" />' . "\n", esc_url( $url ) );
	}

	/**
	 * Open Graph tags.
	 *
	 * @return void
	 */
	private function open_graph(): void {
		$title = wp_get_document_title();
		$url   = $this->current_url();
		$desc  = $this->description();
		$type  = is_singular() ? 'article' : 'website';

		printf( '<meta property="og:title" content="%s" />' . "\n", esc_attr( $title ) );
		printf( '<meta property="og:type" content="%s" />' . "\n", esc_attr( $type ) );
		printf( '<meta property="og:url" content="%s" />' . "\n", esc_url( $url ) );
		printf( '<meta property="og:site_name" content="%s" />' . "\n", esc_attr( get_bloginfo( 'name' ) ) );

		if ( $desc ) {
			printf( '<meta property="og:description" content="%s" />' . "\n", esc_attr( $desc ) );
		}

		$image = $this->image();
		if ( $image ) {
			printf( '<meta property="og:image" content="%s" />' . "\n", esc_url( $image ) );
		}
	}

	/**
	 * Twitter Card tags.
	 *
	 * @return void
	 */
	private function twitter_cards(): void {
		printf( '<meta name="twitter:card" content="summary_large_image" />' . "\n" );
		printf( '<meta name="twitter:title" content="%s" />' . "\n", esc_attr( wp_get_document_title() ) );

		$desc = $this->description();
		if ( $desc ) {
			printf( '<meta name="twitter:description" content="%s" />' . "\n", esc_attr( $desc ) );
		}

		$image = $this->image();
		if ( $image ) {
			printf( '<meta name="twitter:image" content="%s" />' . "\n", esc_url( $image ) );
		}
	}

	/**
	 * Basic Organization / WebSite schema.
	 *
	 * @return void
	 */
	private function schema_organization(): void {
		$data = array(
			'@context' => 'https://schema.org',
			'@type'    => 'WebSite',
			'name'     => get_bloginfo( 'name' ),
			'url'      => home_url( '/' ),
			'potentialAction' => array(
				'@type'       => 'SearchAction',
				'target'      => home_url( '/?s={search_term_string}' ),
				'query-input' => 'required name=search_term_string',
			),
		);

		/**
		 * Filter WebSite schema payload.
		 *
		 * @since 1.0.0
		 *
		 * @param array<string, mixed> $data Schema.
		 */
		$data = apply_filters( 'kutby_schema_website', $data );

		printf(
			'<script type="application/ld+json">%s</script>' . "\n",
			wp_json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE )
		);
	}

	/**
	 * Current request URL.
	 *
	 * @return string
	 */
	private function current_url(): string {
		if ( is_singular() ) {
			return (string) get_permalink();
		}

		global $wp;
		return home_url( add_query_arg( array(), $wp->request ) );
	}

	/**
	 * Meta description candidate.
	 *
	 * @return string
	 */
	private function description(): string {
		if ( is_singular() ) {
			$post = get_post();
			if ( $post && $post->post_excerpt ) {
				return wp_strip_all_tags( $post->post_excerpt );
			}
			if ( $post ) {
				return wp_trim_words( wp_strip_all_tags( $post->post_content ), 30, '…' );
			}
		}

		return (string) get_bloginfo( 'description' );
	}

	/**
	 * Featured image or site icon.
	 *
	 * @return string
	 */
	private function image(): string {
		if ( is_singular() && has_post_thumbnail() ) {
			$url = get_the_post_thumbnail_url( null, 'full' );
			return $url ? $url : '';
		}

		$icon = get_site_icon_url( 512 );
		return $icon ? $icon : '';
	}
}
