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

namespace Ppok\AIToolkit\Tests;

use Ppok\AIToolkit\Abilities\Blocks_Registered;

class Test_Blocks_Registered extends \WP_UnitTestCase {

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

	public function test_descriptor_is_read_only_and_mcp_public(): void {
		$d = Blocks_Registered::descriptor();
		$this->assertFalse( $d['meta']['ppok']['write'], 'blocks-registered is a read.' );
		$this->assertTrue( $d['meta']['mcp']['public'], 'reads are always public at descriptor level.' );
	}

	public function test_input_schema_no_required_props(): void {
		$schema = Blocks_Registered::input_schema();
		$this->assertSame( 'object', $schema['type'] );
		$this->assertFalse( $schema['additionalProperties'] );
		$this->assertArrayHasKey( 'namespace', $schema['properties'] );
		$this->assertArrayNotHasKey( 'required', $schema );
	}

	public function test_permission_callback_requires_edit_posts(): void {
		$subscriber = self::factory()->user->create( array( 'role' => 'subscriber' ) );
		wp_set_current_user( $subscriber );
		$this->assertFalse( Blocks_Registered::permission_callback() );

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

	public function test_execute_returns_array_with_blocks_and_total(): void {
		$out = Blocks_Registered::execute_callback();
		$this->assertArrayHasKey( 'blocks', $out );
		$this->assertArrayHasKey( 'total', $out );
		$this->assertIsArray( $out['blocks'] );
		$this->assertSame( count( $out['blocks'] ), $out['total'] );
		$this->assertGreaterThan( 0, $out['total'], 'Core registers several block types at boot.' );
	}

	public function test_each_block_has_canonical_shape(): void {
		$out = Blocks_Registered::execute_callback();
		$row = $out['blocks'][0];

		foreach ( array( 'name', 'title', 'description', 'category', 'is_dynamic', 'attributes_schema' ) as $key ) {
			$this->assertArrayHasKey( $key, $row, "Row missing key: {$key}" );
		}
		$this->assertIsString( $row['name'] );
		$this->assertIsString( $row['title'] );
		$this->assertIsBool( $row['is_dynamic'] );
	}

	public function test_namespace_filter_restricts_to_prefix(): void {
		// Register a custom test block under a non-core namespace.
		register_block_type(
			'pphpunit/widget',
			array(
				'title'           => 'PPHPUnit Widget',
				'category'        => 'design',
				'render_callback' => '__return_empty_string',
				'attributes'      => array( 'color' => array( 'type' => 'string' ) ),
			)
		);

		$only_pphpunit = Blocks_Registered::execute_callback( array( 'namespace' => 'pphpunit' ) );
		$names         = array_column( $only_pphpunit['blocks'], 'name' );

		$this->assertContains( 'pphpunit/widget', $names );
		$this->assertNotContains( 'core/paragraph', $names, 'core/* must be excluded when namespace=pphpunit.' );

		unregister_block_type( 'pphpunit/widget' );
	}

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

	public function test_is_dynamic_reflects_render_callback(): void {
		register_block_type(
			'pphpunit/dynamic',
			array(
				'title'           => 'PPHPUnit Dynamic',
				'render_callback' => '__return_empty_string',
			)
		);
		register_block_type(
			'pphpunit/static',
			array(
				'title' => 'PPHPUnit Static',
			)
		);

		$out = Blocks_Registered::execute_callback( array( 'namespace' => 'pphpunit' ) );
		$by_name = array();
		foreach ( $out['blocks'] as $row ) {
			$by_name[ $row['name'] ] = $row;
		}

		$this->assertTrue( $by_name['pphpunit/dynamic']['is_dynamic'] );
		$this->assertFalse( $by_name['pphpunit/static']['is_dynamic'] );

		unregister_block_type( 'pphpunit/dynamic' );
		unregister_block_type( 'pphpunit/static' );
	}

	public function test_example_returns_array(): void {
		$ex = Blocks_Registered::example();
		$this->assertIsArray( $ex );
		$this->assertArrayHasKey( 'namespace', $ex );
	}
}
