<?php
/**
 * Ability: wp-agent/set-post-status
 *
 * Setzt den Status eines Beitrags oder einer Seite direkt (publish, draft,
 * pending, private, future). Dies ist eine explizite Status-Ability: der
 * Aufrufer will genau diesen Status setzen, deshalb gibt es hier KEIN
 * zusätzliches Draft-by-default-Gate wie in der CLI-Artikel-Pipeline. Das
 * Ergebnis meldet klar, welcher Status tatsächlich persistiert wurde.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_set_post_status(): array {
	return array(
		'label'               => __( 'Beitragsstatus setzen', 'wp-agent-companion' ),
		'description'         => __( 'Setzt den Status eines Beitrags oder einer Seite direkt (publish, draft, pending, private, future). Bei future ist ein in der Zukunft liegendes Datum Pflicht. Re-Read-verifiziert.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array(
				'post_id' => array( 'type' => 'integer' ),
				'status'  => array(
					'type' => 'string',
					'enum' => array( 'publish', 'draft', 'pending', 'private', 'future' ),
				),
				'date'    => array(
					'type'        => 'string',
					'description' => __( 'Pflicht bei status=future; parsebares Datum, muss in der Zukunft liegen. Angaben ohne Zeitzone werden als Website-Zeit interpretiert.', 'wp-agent-companion' ),
				),
			),
			'required'   => array( 'post_id', 'status' ),
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'post_id'  => array( 'type' => 'integer' ),
				'status'   => array( 'type' => 'string' ),
				'verified' => array( 'type' => 'boolean' ),
			),
		),
		'execute_callback'    => 'wpagent_exec_set_post_status',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array(
				'readonly'    => false,
				'destructive' => false,
				'idempotent'  => true,
			),
		),
	);
}

/**
 * @param mixed $input
 * @return array|WP_Error
 */
function wpagent_exec_set_post_status( $input ) {
	$input   = is_array( $input ) ? $input : array();
	$post_id = (int) ( $input['post_id'] ?? 0 );
	$post    = get_post( $post_id );

	if ( ! $post ) {
		return new WP_Error( 'wpagent_no_post', __( 'Beitrag nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}

	$status  = (string) ( $input['status'] ?? '' );
	$allowed = array( 'publish', 'draft', 'pending', 'private', 'future' );
	if ( ! in_array( $status, $allowed, true ) ) {
		return new WP_Error( 'wpagent_bad_status', sprintf( __( 'Ungültiger Status "%s".', 'wp-agent-companion' ), $status ), array( 'status' => 400 ) );
	}
	$status_cap = wpagent_check_post_status_cap( $post->post_type, $status );
	if ( is_wp_error( $status_cap ) ) {
		return $status_cap;
	}

	$postarr = array(
		'ID'          => $post_id,
		'post_status' => $status,
	);

	if ( 'future' === $status ) {
		$date_input = (string) ( $input['date'] ?? '' );
		if ( '' === $date_input ) {
			return new WP_Error( 'wpagent_missing_date', __( 'status=future benötigt ein Datum.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$parsed_date = wpagent_parse_post_date( $date_input );
		if ( is_wp_error( $parsed_date ) ) {
			return $parsed_date;
		}
		if ( $parsed_date['timestamp'] <= time() ) {
			return new WP_Error( 'wpagent_date_not_future', __( 'Das Datum muss in der Zukunft liegen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$postarr['post_date']     = $parsed_date['post_date'];
		$postarr['post_date_gmt'] = $parsed_date['post_date_gmt'];
		// wp_update_post() merged das alte post_date_gmt sonst einfach durch
		// array_merge() über unser neues post_date hinweg (wir setzen nur
		// post_date, das alte post_date_gmt überlebt den Merge unverändert und
		// gewinnt in wp_insert_post()s eigener "ist post_date_gmt leer?"-Prüfung).
		// Zusätzlich überschreibt WordPress' eigene "Drafts shouldn't be assigned
		// a date"-Logik unser Datum komplett mit "jetzt", wenn der AKTUELLE Status
		// draft/pending/auto-draft ist und post_date_gmt beim Beitrag noch der
		// Nullwert ist (der Normalfall für frische Entwürfe) — außer edit_date ist
		// gesetzt. Das ist exakt das Flag, das auch der Bearbeiten-Bildschirm bei
		// einer manuellen Datumsänderung mitschickt.
		$postarr['edit_date'] = true;
	} elseif ( 'publish' === $status && ( 'future' === $post->post_status || wpagent_post_has_future_date( $post ) ) ) {
		$postarr['post_date']     = current_time( 'mysql' );
		$postarr['post_date_gmt'] = current_time( 'mysql', true );
		$postarr['edit_date']     = true;
	}

	$res = wp_update_post( $postarr, true );
	if ( is_wp_error( $res ) ) {
		return $res;
	}

	$fresh    = get_post( $post_id );
	$verified = ( $fresh instanceof WP_Post && $status === $fresh->post_status );

	return array(
		'post_id'  => $post_id,
		'status'   => $fresh ? $fresh->post_status : '',
		'verified' => $verified,
	);
}
