<?php
/**
 * Ability: wp-agent/list-media
 *
 * Read-only. Listet Medienbeiträge (post_type=attachment, post_status=inherit,
 * also ohne Papierkorb) mit optionalem Such-, MIME-Typ- und
 * Paginierungs-Filter als schlanke Liste (id, title, url, mime_type, alt,
 * date) plus Gesamtzahl. Analog zu list-posts.php, aber auf den festen
 * post_type attachment zugeschnitten.
 *
 * @package WPAgentCompanion
 */

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

if ( ! function_exists( 'wpagent_perm_upload_files' ) ) {
	/**
	 * Permission callback: der Aufrufer muss Dateien hochladen dürfen.
	 *
	 * Absichtlich als eigene, mit function_exists() abgesicherte Definition in
	 * dieser Datei statt in includes/helpers.php: Diese Phase legt
	 * ausschließlich neue Dateien an, geteilte Dateien bleiben der
	 * Integrationsphase vorbehalten. Dieselbe Definition steht identisch
	 * (function_exists()-geschützt) auch in upload-media.php, damit keine
	 * Ladereihenfolge zwischen den beiden neuen Medien-Ability-Dateien
	 * vorausgesetzt werden muss. Die Integrationsphase sollte diese Funktion
	 * neben die anderen vier wpagent_perm_*-Helfer nach helpers.php heben.
	 *
	 * @param mixed $input Ungenutzter Ability-Input.
	 * @return bool
	 */
	function wpagent_perm_upload_files( $input = null ): bool {
		return current_user_can( 'upload_files' );
	}
}

function wpagent_ability_list_media(): array {
	return array(
		'label'               => __( 'Medienbeiträge auflisten', 'wp-agent-companion' ),
		'description'         => __( 'Listet Medienbeiträge mit Suche, MIME-Typ- und Paginierungs-Filter als schlanke Liste (id, title, url, mime_type, alt, date) plus Gesamtzahl.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'search'    => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100 ),
				'mime_type' => array(
					'type'        => 'string', 'minLength' => 1, 'maxLength' => 100,
					'description' => __( 'Voller MIME-Typ (z. B. image/png) oder Präfix (z. B. image), wie post_mime_type in WP_Query.', 'wp-agent-companion' ),
				),
				'per_page'  => array(
					'type'    => 'integer', 'minimum' => 1, 'maximum' => 100,
					'default' => 20,
				),
				'page'      => array(
					'type'    => 'integer', 'minimum' => 1, 'maximum' => 10000,
					'default' => 1,
				),
			),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'items' => array(
					'type'  => 'array', 'maxItems' => 100,
					'items' => array(
						'type'                 => 'object',
						'properties'           => array(
							'id'        => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => 2147483647 ),
							'title'     => array( 'type' => 'string', 'maxLength' => 200 ),
							'url'       => array( 'type' => 'string', 'maxLength' => 2048 ),
							'mime_type' => array( 'type' => 'string', 'maxLength' => 100 ),
							'alt'       => array( 'type' => 'string', 'maxLength' => 1000 ),
							'date'      => array( 'type' => 'string', 'maxLength' => 32 ),
							'state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
						),
						'required'             => array( 'id', 'title', 'url', 'mime_type', 'alt', 'date', 'state_hash' ),
						'additionalProperties' => false,
					),
				),
				'total' => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 2147483647 ),
			),
			'required'             => array( 'items', 'total' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_list_media',
		'permission_callback' => 'wpagent_perm_upload_files',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => true,
				'destructive' => false,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array
 */
function wpagent_exec_list_media( $input ) {
	$input = is_array( $input ) ? $input : array();

	$per_page = 20;
	if ( array_key_exists( 'per_page', $input ) ) {
		$per_page = wpagent_core_schema_input_integer( $input['per_page'], 1, 100, 'per_page' );
		if ( is_wp_error( $per_page ) ) {
			return $per_page;
		}
	}

	$page = 1;
	if ( array_key_exists( 'page', $input ) ) {
		$page = wpagent_core_schema_input_integer( $input['page'], 1, 10000, 'page' );
		if ( is_wp_error( $page ) ) {
			return $page;
		}
	}

	$query_args = array(
		'post_type'           => 'attachment',
		// Explizit statt dem impliziten WP_Query-Default für Attachments:
		// zeigt nur angehängte/sichtbare Medien, nie den Papierkorb.
		'post_status'         => 'inherit',
		'posts_per_page'      => $per_page,
		'paged'               => $page,
		'orderby'             => 'date',
		'order'               => 'DESC',
		'ignore_sticky_posts' => true,
	);
	if ( array_key_exists( 'search', $input ) ) {
		$search = wpagent_core_mutator_bounded_text( $input['search'], 100 );
		if ( is_wp_error( $search ) ) {
			return $search;
		}
		$query_args['s'] = $search;
	}
	if ( array_key_exists( 'mime_type', $input ) ) {
		$mime_type = wpagent_core_mutator_bounded_text( $input['mime_type'], 100 );
		if ( is_wp_error( $mime_type ) ) {
			return $mime_type;
		}
		$query_args['post_mime_type'] = $mime_type;
	}

	$query = new WP_Query( $query_args );

	$items = array();
	foreach ( $query->posts as $post ) {
		$alt_values = get_post_meta( $post->ID, '_wp_attachment_image_alt', false );
		$alt_valid  = is_array( $alt_values );
		if ( $alt_valid ) {
			foreach ( $alt_values as $value ) {
				if ( ! is_string( $value ) ) {
					$alt_valid = false;
					break;
				}
			}
		}
		$alt_values = $alt_valid ? array_values( $alt_values ) : array();
		$item = array(
			'id'        => (int) $post->ID,
			'title'     => wpagent_core_schema_output_text( $post->post_title, 200, 'items.title' ),
			'url'       => wpagent_core_schema_output_text( (string) wp_get_attachment_url( $post->ID ), 2048, 'items.url' ),
			'mime_type' => wpagent_core_schema_output_text( $post->post_mime_type, 100, 'items.mime_type' ),
			'alt'       => wpagent_core_schema_output_text( $alt_values[0] ?? '', 1000, 'items.alt' ),
			'date'      => wpagent_core_schema_output_text( $post->post_date, 32, 'items.date' ),
			'state_hash' => wpagent_attachment_alt_state_hash( $post, $alt_values ),
		);
		foreach ( $item as $value ) {
			if ( is_wp_error( $value ) ) {
				return $value;
			}
		}
		$items[] = $item;
	}
	$items = wpagent_core_schema_output_list( $items, 100, 'items' );
	if ( is_wp_error( $items ) ) {
		return $items;
	}
	$total = (int) $query->found_posts;
	if ( $total < 0 || $total > 2147483647 ) {
		return new WP_Error( 'wpagent_core_schema_output_overflow', __( 'Die Gesamtzahl der Medien überschreitet die veröffentlichte Sicherheitsgrenze.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}

	return array(
		'items' => $items,
		'total' => $total,
	);
}
