<?php
/**
 * Tests for ppok/patterns-registered.
 *
 * @package Ppok\AIToolkit\Tests
 * @license GPL-2.0-or-later
 */

namespace Ppok\AIToolkit\Tests;

use Ppok\AIToolkit\Abilities\Patterns_Registered;

class Test_Patterns_Registered extends \WP_UnitTestCase {

	private function registry(): \WP_Block_Patterns_Registry {
		return \WP_Block_Patterns_Registry::get_instance();
	}

	public function setUp(): void {
		parent::setUp();
		register_block_pattern(
			'pphpunit/hero',
			array(
				'title'         => 'PPHPUnit Hero',
				'description'   => 'A hero used in tests.',
				'content'       => "<!-- wp:heading -->\n<h2>Hi</h2>\n<!-- /wp:heading -->",
				'categories'    => array( 'featured', 'header' ),
				'keywords'      => array( 'hero', 'banner' ),
				'viewportWidth' => 1280,
				'blockTypes'    => array( 'core/post-content' ),
				'postTypes'     => array( 'page' ),
				'source'        => 'plugin',
			)
		);
		register_block_pattern(
			'pphpunit/footer',
			array(
				'title'      => 'PPHPUnit Footer',
				'content'    => "<!-- wp:paragraph -->\n<p>©</p>\n<!-- /wp:paragraph -->",
				'categories' => array( 'footer' ),
				'source'     => 'plugin',
			)
		);
	}

	public function tearDown(): void {
		if ( $this->registry()->is_registered( 'pphpunit/hero' ) ) {
			unregister_block_pattern( 'pphpunit/hero' );
		}
		if ( $this->registry()->is_registered( 'pphpunit/footer' ) ) {
			unregister_block_pattern( 'pphpunit/footer' );
		}
		parent::tearDown();
	}

	public function test_slug_constant(): void {
		$this->assertSame( 'ppok/patterns-registered', Patterns_Registered::SLUG );
	}

	public function test_descriptor_is_read_only_and_mcp_public(): void {
		$d = Patterns_Registered::descriptor();
		$this->assertFalse( $d['meta']['ppok']['write'] );
		$this->assertTrue( $d['meta']['mcp']['public'] );
	}

	public function test_permission_requires_edit_posts(): void {
		wp_set_current_user( 0 );
		$this->assertFalse( Patterns_Registered::permission_callback() );

		$editor = self::factory()->user->create( array( 'role' => 'editor' ) );
		wp_set_current_user( $editor );
		$this->assertTrue( Patterns_Registered::permission_callback() );
	}

	public function test_execute_returns_patterns_and_total(): void {
		$out = Patterns_Registered::execute_callback();
		$this->assertArrayHasKey( 'patterns', $out );
		$this->assertArrayHasKey( 'total', $out );
		$this->assertSame( count( $out['patterns'] ), $out['total'] );
	}

	public function test_pattern_shape_includes_all_metadata(): void {
		$out  = Patterns_Registered::execute_callback();
		$hero = null;
		foreach ( $out['patterns'] as $p ) {
			if ( 'pphpunit/hero' === $p['name'] ) {
				$hero = $p;
				break;
			}
		}

		$this->assertNotNull( $hero, 'Test pattern must be present in output.' );
		$this->assertSame( 'PPHPUnit Hero', $hero['title'] );
		$this->assertSame( 'A hero used in tests.', $hero['description'] );
		$this->assertSame( array( 'featured', 'header' ), $hero['categories'] );
		$this->assertSame( array( 'hero', 'banner' ), $hero['keywords'] );
		$this->assertSame( 1280, $hero['viewport_width'] );
		$this->assertSame( array( 'core/post-content' ), $hero['block_types'] );
		$this->assertSame( array( 'page' ), $hero['post_types'] );
		$this->assertSame( 'plugin', $hero['source'] );
		$this->assertTrue( $hero['inserter'] );
		$this->assertStringContainsString( '<!-- wp:heading -->', $hero['content'] );
	}

	public function test_category_filter_restricts_results(): void {
		$out   = Patterns_Registered::execute_callback( array( 'category' => 'footer' ) );
		$names = array_column( $out['patterns'], 'name' );

		$this->assertContains( 'pphpunit/footer', $names );
		$this->assertNotContains( 'pphpunit/hero', $names, 'hero is not in the footer category.' );
	}

	public function test_include_content_false_omits_content_field(): void {
		$out  = Patterns_Registered::execute_callback( array( 'include_content' => false ) );
		$hero = null;
		foreach ( $out['patterns'] as $p ) {
			if ( 'pphpunit/hero' === $p['name'] ) {
				$hero = $p;
				break;
			}
		}

		$this->assertNotNull( $hero );
		$this->assertArrayNotHasKey( 'content', $hero, 'content must be omitted when include_content=false.' );
	}

	public function test_results_sorted_alphabetically_by_name(): void {
		$out   = Patterns_Registered::execute_callback();
		$names = array_column( $out['patterns'], 'name' );
		$sorted = $names;
		sort( $sorted, SORT_STRING );
		$this->assertSame( $sorted, $names );
	}

	public function test_example_returns_array(): void {
		$ex = Patterns_Registered::example();
		$this->assertIsArray( $ex );
	}
}
