<?php
/**
 * Post type extension registry.
 *
 * @package SmartyPress_AI_Engine
 */

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

/**
 * Selects and applies post type specific extensions.
 */
class SmartyPress_AI_Post_Type_Extension_Registry {

	/**
	 * Registered extensions.
	 *
	 * @var SmartyPress_AI_Post_Type_Extension_Interface[]
	 */
	private $extensions = array();

	/**
	 * Constructor.
	 *
	 * @param array $extensions Initial extensions.
	 */
	public function __construct( array $extensions = array() ) {
		foreach ( $extensions as $extension ) {
			$this->register( $extension );
		}

		/**
		 * Filters post type generation extensions.
		 *
		 * @param array $extensions Registered extensions.
		 */
		$filtered = apply_filters( 'smartypress_ai_content_post_type_extensions', $this->extensions );
		if ( is_array( $filtered ) ) {
			$this->extensions = array_values(
				array_filter(
					$filtered,
					function ( $extension ) {
						return $extension instanceof SmartyPress_AI_Post_Type_Extension_Interface;
					}
				)
			);
		}
	}

	/**
	 * Register an extension.
	 *
	 * @param mixed $extension Extension instance.
	 * @return void
	 */
	public function register( $extension ) {
		if ( $extension instanceof SmartyPress_AI_Post_Type_Extension_Interface ) {
			$this->extensions[] = $extension;
		}
	}

	/**
	 * Get matching extensions.
	 *
	 * @param string $post_type Post type.
	 * @param array  $settings Generation settings.
	 * @return SmartyPress_AI_Post_Type_Extension_Interface[]
	 */
	public function get_for_post_type( $post_type, array $settings ) {
		$post_type = sanitize_key( $post_type );

		return array_values(
			array_filter(
				$this->extensions,
				function ( $extension ) use ( $post_type, $settings ) {
					return $extension->supports( $post_type, $settings );
				}
			)
		);
	}

	/**
	 * Get generation rules.
	 *
	 * @param string $post_type Post type.
	 * @param array  $settings Generation settings.
	 * @return array
	 */
	public function get_generation_rules( $post_type, array $settings ) {
		$rules = array();
		foreach ( $this->get_for_post_type( $post_type, $settings ) as $extension ) {
			$rules = array_merge( $rules, $extension->get_generation_rules( $settings ) );
		}

		return apply_filters( 'smartypress_ai_content_generation_rules', $rules, $post_type, $settings );
	}

	/**
	 * Get SEO optimization rules.
	 *
	 * @param string $post_type Post type.
	 * @param array  $settings Generation settings.
	 * @return array
	 */
	public function get_seo_rules( $post_type, array $settings ) {
		$rules = array();
		foreach ( $this->get_for_post_type( $post_type, $settings ) as $extension ) {
			$rules = array_merge( $rules, $extension->get_seo_rules( $settings ) );
		}

		return apply_filters( 'smartypress_ai_content_seo_rules', $rules, $post_type, $settings );
	}

	/**
	 * Build item context.
	 *
	 * @param string $post_type Post type.
	 * @param array  $item Queue item.
	 * @param array  $settings Generation settings.
	 * @return string
	 */
	public function build_item_context( $post_type, array $item, array $settings ) {
		$parts = array();
		foreach ( $this->get_for_post_type( $post_type, $settings ) as $extension ) {
			$context = trim( (string) $extension->build_item_context( $item, $settings ) );
			if ( '' !== $context ) {
				$parts[] = $context;
			}
		}

		return (string) apply_filters( 'smartypress_ai_content_item_context', trim( implode( "\n\n", $parts ) ), $post_type, $item, $settings );
	}

	/**
	 * Prepare post data.
	 *
	 * @param array $post_data Generated post data.
	 * @param array $item Queue item.
	 * @param array $settings Generation settings.
	 * @return array
	 */
	public function prepare_post_data( array $post_data, array $item, array $settings ) {
		$post_type = sanitize_key( $post_data['post_type'] ?? $settings['post_type'] ?? 'post' );
		foreach ( $this->get_for_post_type( $post_type, $settings ) as $extension ) {
			$post_data = $extension->prepare_post_data( $post_data, $item, $settings );
		}

		return apply_filters( 'smartypress_ai_content_prepared_post_data', $post_data, $item, $settings );
	}

	/**
	 * Apply metadata after post persistence.
	 *
	 * @param int   $post_id Post ID.
	 * @param array $post_data Generated post data.
	 * @param array $item Queue item.
	 * @param array $settings Generation settings.
	 * @return void
	 */
	public function apply_metadata( $post_id, array $post_data, array $item, array $settings ) {
		$post_type = sanitize_key( $post_data['post_type'] ?? $settings['post_type'] ?? 'post' );
		foreach ( $this->get_for_post_type( $post_type, $settings ) as $extension ) {
			$extension->apply_metadata( $post_id, $post_data, $item, $settings );
		}

		do_action( 'smartypress_ai_content_after_post_persisted', $post_id, $post_data, $item, $settings );
	}
}
