<?php
/**
 * Abilities für WooCommerce-Produkte.
 *
 * @package WPAgentCompanion
 */

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

function wpagent_ability_list_products(): array {
	return array(
		'label' => __( 'Produkte auflisten', 'wp-agent-companion' ),
		'description' => __( 'Sucht und filtert WooCommerce-Produkte über den offiziellen Product Query und Data Store.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object',
			'properties' => array(
				'search' => array( 'type' => 'string', 'maxLength' => 200 ),
				'sku' => array( 'type' => 'string', 'maxLength' => 191 ),
				'status' => array( 'type' => 'string', 'enum' => array( 'draft', 'publish', 'pending', 'private' ) ),
				'type' => array( 'type' => 'string', 'enum' => array( 'simple', 'variable', 'grouped', 'external' ) ),
				'page' => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => WPAGENT_WC_READ_MAX_PAGE ),
				'per_page' => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => WPAGENT_WC_READ_MAX_CATALOG_ITEMS ),
			),
			'additionalProperties' => false,
		),
		'output_schema' => wpagent_wc_catalog_read_schema(),
		'execute_callback' => 'wpagent_exec_list_products',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ) ),
	);
}

function wpagent_ability_create_product(): array {
	return array(
		'label' => __( 'Produkt erstellen', 'wp-agent-companion' ),
		'description' => __( 'Erstellt ein einfaches oder variables WooCommerce-Produkt über die nativen Produktobjekte und verifiziert das Ergebnis.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type'                 => 'object',
			'properties'           => wpagent_wc_product_input_properties( false ),
			'required'             => array( 'type', 'name' ),
			'additionalProperties' => false,
		),
		'output_schema' => array(
			'type'                 => 'object',
			'properties'           => array(
				'product'  => wpagent_wc_product_read_schema(),
				'verified' => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'product', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback' => 'wpagent_exec_create_product',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

function wpagent_ability_delete_product(): array {
	return array(
		'label' => __( 'Produkt in den Papierkorb verschieben', 'wp-agent-companion' ),
		'description' => __( 'Verschiebt ein WooCommerce-Produkt reversibel in den Papierkorb. Endgültiges Löschen ist über diesen Remote-Pfad nicht verfügbar. confirm=true ist zwingend erforderlich.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'properties' => array( 'product_id' => array( 'type' => 'integer', 'minimum' => 1 ), 'expected_state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ), 'confirm' => array( 'type' => 'boolean' ), 'force' => array( 'type' => 'boolean' ), 'permanent' => array( 'type' => 'boolean' ) ), 'required' => array( 'product_id', 'expected_state_hash', 'confirm' ), 'additionalProperties' => false ),
		'output_schema' => array( 'type' => 'object', 'properties' => array( 'product_id' => array( 'type' => 'integer' ), 'trashed' => array( 'type' => 'boolean' ) ) ),
		'execute_callback' => 'wpagent_exec_delete_product',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return array<string, mixed> */
function wpagent_wc_product_input_properties( bool $include_id = true ): array {
	$properties = array(
		'type' => array( 'type' => 'string', 'enum' => array( 'simple', 'variable' ) ),
		'name' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 255 ),
		'status' => array( 'type' => 'string', 'enum' => array( 'draft', 'publish', 'pending', 'private' ) ),
		'sku' => array( 'type' => 'string', 'maxLength' => 191 ),
		'regular_price' => array( 'type' => 'string', 'maxLength' => 32 ),
		'sale_price' => array( 'type' => 'string', 'maxLength' => 32 ),
		'manage_stock' => array( 'type' => 'boolean' ),
		'stock_quantity' => array( 'type' => 'integer' ),
		'stock_status' => array( 'type' => 'string', 'enum' => array( 'instock', 'outofstock', 'onbackorder' ) ),
		'short_description' => array( 'type' => 'string', 'maxLength' => 10000 ),
		'description' => array( 'type' => 'string', 'maxLength' => 200000 ),
		'virtual' => array( 'type' => 'boolean' ),
		'downloadable' => array( 'type' => 'boolean' ),
		'featured' => array( 'type' => 'boolean' ),
		'catalog_visibility' => array( 'type' => 'string', 'enum' => array( 'visible', 'catalog', 'search', 'hidden' ) ),
		'weight' => array( 'type' => 'string', 'maxLength' => 32 ),
		'length' => array( 'type' => 'string', 'maxLength' => 32 ),
		'width' => array( 'type' => 'string', 'maxLength' => 32 ),
		'height' => array( 'type' => 'string', 'maxLength' => 32 ),
		'image_id' => array( 'type' => 'integer', 'minimum' => 0 ),
		'gallery_image_ids' => array( 'type' => 'array', 'maxItems' => 100, 'items' => array( 'type' => 'integer', 'minimum' => 1 ) ),
		'category_ids' => array( 'type' => 'array', 'maxItems' => 100, 'items' => array( 'type' => 'integer', 'minimum' => 1 ) ),
		'tag_ids' => array( 'type' => 'array', 'maxItems' => 100, 'items' => array( 'type' => 'integer', 'minimum' => 1 ) ),
		'shipping_class_id' => array( 'type' => 'integer', 'minimum' => 0 ),
		'attributes' => array( 'type' => 'array', 'maxItems' => 50, 'items' => wpagent_wc_product_attribute_input_schema() ),
	);
	if ( $include_id ) {
		$properties = array( 'product_id' => array( 'type' => 'integer', 'minimum' => 1 ) ) + $properties;
	}
	return $properties;
}

/** @return array<string,mixed> */
function wpagent_wc_product_attribute_input_schema(): array {
	return array(
		'type'                 => 'object',
		'properties'           => array(
			'name'      => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ),
			'options'   => array( 'type' => 'array', 'minItems' => 1, 'maxItems' => 100, 'items' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ) ),
			'visible'   => array( 'type' => 'boolean' ),
			'variation' => array( 'type' => 'boolean' ),
		),
		'required'             => array( 'name', 'options' ),
		'additionalProperties' => false,
	);
}

/** @return array|WP_Error */
function wpagent_exec_list_products( $input ) {
	$input = is_array( $input ) ? $input : array();
	$available = wpagent_require_woocommerce();
	if ( is_wp_error( $available ) ) return $available;
	if ( ! current_user_can( 'edit_products' ) ) return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );

	$pagination = wpagent_wc_read_pagination_input( $input );
	if ( is_wp_error( $pagination ) ) return $pagination;
	$page = $pagination['page'];
	$limit = $pagination['per_page'];
	$args = array( 'limit' => $limit, 'page' => $page, 'paginate' => true, 'orderby' => 'date', 'order' => 'DESC', 'return' => 'objects' );
	foreach ( array( 'sku', 'status', 'type' ) as $key ) {
		if ( isset( $input[ $key ] ) && '' !== $input[ $key ] ) $args[ $key ] = (string) $input[ $key ];
	}
	if ( isset( $input['search'] ) && '' !== trim( (string) $input['search'] ) ) {
		$data_store = WC_Data_Store::load( 'product' );
		if ( ! is_object( $data_store ) || ! is_callable( array( $data_store, 'search_products' ) ) ) {
			return wpagent_wc_read_contract_error( 'mismatch', 'search_provider' );
		}
		try {
			$ids = wpagent_wc_read_search_ids( $data_store->search_products( trim( (string) $input['search'] ), '', false, true, WPAGENT_WC_READ_MAX_SEARCH_CANDIDATES ) );
		} catch ( Throwable $error ) {
			return wpagent_wc_read_contract_error( 'mismatch', 'search_provider' );
		}
		if ( is_wp_error( $ids ) ) {
			return $ids;
		}
		if ( array() === $ids ) return array( 'products' => array(), 'total' => 0, 'pages' => 0 );
		$args['include'] = $ids;
	}
	$query = new WC_Product_Query( $args );
	$result = $query->get_products();
	if ( ! is_object( $result ) || ! isset( $result->products, $result->total, $result->max_num_pages ) ) {
		return wpagent_wc_read_contract_error( 'mismatch', 'catalog' );
	}
	return wpagent_wc_read_catalog_payload( $result->products, $result->total, $result->max_num_pages, $limit );
}

/** @return array|WP_Error */
function wpagent_exec_create_product( $input ) {
	$input = is_array( $input ) ? $input : array();
	$available = wpagent_require_woocommerce();
	if ( is_wp_error( $available ) ) return $available;
	if ( ! current_user_can( wpagent_post_type_create_cap( 'product' ) ) ) return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	$type = (string) ( $input['type'] ?? '' );
	$name = trim( (string) ( $input['name'] ?? '' ) );
	if ( ! in_array( $type, array( 'simple', 'variable' ), true ) || '' === $name ) return new WP_Error( 'wpagent_bad_product_value', __( 'type und name sind erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$status = (string) ( $input['status'] ?? 'draft' );
	$status_cap = wpagent_check_post_status_cap( 'product', $status );
	if ( is_wp_error( $status_cap ) ) return $status_cap;
	$save_started = false;
	try {
		$product = 'variable' === $type ? new WC_Product_Variable() : new WC_Product_Simple();
		$product->set_name( $name );
		$product->set_status( $status );
		$applied = wpagent_wc_apply_product_fields( $product, $input );
		if ( is_wp_error( $applied ) ) {
			return $applied;
		}
		$expected = wpagent_wc_capture_product_fields( $product, array_values( array_unique( array_merge( array( 'name', 'status', 'type' ), $applied ) ) ) );
		$save_started = true;
		$product_id = $product->save();
	} catch ( WC_Data_Exception $e ) {
		if ( $save_started ) {
			return wpagent_wc_recovery_required( 'product', __( 'WooCommerce hat die Produkterstellung nach ihrem Start abgebrochen. Wiederhole sie nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) );
		}
		return new WP_Error( 'wpagent_wc_invalid', $e->getMessage(), array( 'status' => 400 ) );
	} catch ( Throwable $error ) {
		return $save_started
			? wpagent_wc_recovery_required( 'product', __( 'WooCommerce hat bei der Produkterstellung einen Fehler ausgelöst. Wiederhole sie nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) )
			: new WP_Error( 'wpagent_wc_invalid', __( 'Die Produktdaten konnten nicht sicher vorbereitet werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$fresh = wpagent_wc_fresh_product( $product_id );
	if ( ! $fresh instanceof WC_Product ) {
		return wpagent_wc_recovery_required( 'product', __( 'Das erstellte Produkt konnte nicht erneut gelesen werden. Wiederhole die Anlage nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) );
	}
	$verification = wpagent_wc_verify_product_fields( $fresh, $expected );
	if ( ! $verification['verified'] ) {
		return wpagent_wc_recovery_required( 'product', __( 'Das erstellte Produkt weicht nach dem WooCommerce-Schreibvorgang vom Zielzustand ab. Es wurde kein automatisches Rollback ausgeführt. Prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ), wpagent_wc_product_payload( $fresh )['state_hash'] );
	}
	$readback = wpagent_wc_read_product_payload( $fresh );
	if ( is_wp_error( $readback ) ) {
		return wpagent_wc_recovery_required( 'product', __( 'Das erstellte Produkt verletzt den sicheren Lesevertrag. Es wurde kein automatisches Rollback ausgeführt. Prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) );
	}
	return array( 'product' => $readback, 'verified' => true );
}

/** @return array|WP_Error */
function wpagent_exec_delete_product( $input ) {
	$input = is_array( $input ) ? $input : array();
	$product_id = (int) ( $input['product_id'] ?? 0 );
	$product = wpagent_get_editable_product( $product_id );
	if ( is_wp_error( $product ) ) return $product;
	if ( ! current_user_can( 'delete_post', $product_id ) ) return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	if ( true === ( $input['force'] ?? false ) || true === ( $input['permanent'] ?? false ) ) return new WP_Error( 'wpagent_wc_permanent_delete_unavailable', __( 'Das endgültige Löschen von WooCommerce-Produkten ist über diesen Remote-Pfad nicht verfügbar. Verschiebe das Produkt stattdessen reversibel in den Papierkorb.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	if ( ! EMPTY_TRASH_DAYS ) return new WP_Error( 'wpagent_wc_product_trash_unavailable', __( 'Der WordPress-Papierkorb ist deaktiviert. WPAgently führt deshalb keine potenziell endgültige Produktlöschung aus.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	if ( true !== ( $input['confirm'] ?? false ) ) return new WP_Error( 'wpagent_confirmation_required', __( 'Zum Verschieben in den Papierkorb ist confirm=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$lock = wpagent_wc_acquire_product_lock( $product_id );
	if ( is_wp_error( $lock ) ) return $lock;
	$delete_started = false;
	try {
		// The preflight above can have filled WooCommerce's request cache. CAS
		// must operate on a re-read performed after the scoped lock was acquired.
		wpagent_wc_forget_product_cache( $product_id );
		$product = wpagent_get_editable_product( $product_id );
		if ( is_wp_error( $product ) ) return $product;
		$previous = wpagent_wc_product_payload( $product );
		$cas = wpagent_wc_require_expected_state_hash( $input, $previous, 'product' );
		if ( is_wp_error( $cas ) ) return $cas;
		if ( 'trash' === $product->get_status() ) return new WP_Error( 'wpagent_wc_product_already_trashed', __( 'Das Produkt befindet sich bereits im Papierkorb. WPAgently führt keinen weiteren Löschvorgang aus.', 'wp-agent-companion' ), array( 'status' => 409, 'current_state_hash' => $previous['state_hash'] ) );
		if ( ! wpagent_wc_product_lock_checkpoint( $product_id, $lock ) ) {
			return wpagent_wc_recovery_required( 'product', __( 'Die exklusive Produktsperre ging vor dem Papierkorb-Vorgang verloren. Der Zustand bleibt unverändert und muss neu gelesen werden.', 'wp-agent-companion' ), $previous['state_hash'] );
		}
		// WordPress/WooCommerce offer no conditional trash primitive. Re-read the
		// exact public product state immediately before the irreversible provider
		// call so native wp-admin writes during the request fail closed.
		do_action( 'wpagent_wc_before_product_trash_preflight', $product_id );
		$product = wpagent_wc_fresh_product( $product_id );
		if ( ! $product instanceof WC_Product ) {
			return wpagent_wc_recovery_required( 'product', __( 'Das Produkt konnte unmittelbar vor dem Papierkorb-Vorgang nicht sicher erneut gelesen werden. Wiederhole ihn nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ), $previous['state_hash'] );
		}
		$pre_trash = wpagent_wc_product_payload( $product );
		$cas       = wpagent_wc_require_expected_state_hash( $input, $pre_trash, 'product' );
		if ( is_wp_error( $cas ) ) {
			return $cas;
		}
		if ( 'trash' === $product->get_status() ) {
			return new WP_Error( 'wpagent_wc_product_already_trashed', __( 'Das Produkt befindet sich bereits im Papierkorb. WPAgently führt keinen weiteren Löschvorgang aus.', 'wp-agent-companion' ), array( 'status' => 409, 'current_state_hash' => $pre_trash['state_hash'] ) );
		}
		if ( ! current_user_can( 'delete_post', $product_id ) ) {
			return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung.', 'wp-agent-companion' ), array( 'status' => 403 ) );
		}
		if ( ! wpagent_wc_product_lock_checkpoint( $product_id, $lock ) ) {
			return wpagent_wc_recovery_required( 'product', __( 'Die exklusive Produktsperre ging unmittelbar vor dem Papierkorb-Vorgang verloren. Der Zustand bleibt unverändert und muss neu gelesen werden.', 'wp-agent-companion' ), $pre_trash['state_hash'] );
		}
		$delete_started = true;
		$trashed = $product->delete();
		if ( ! wpagent_wc_product_lock_checkpoint( $product_id, $lock ) ) {
			return wpagent_wc_recovery_required( 'product', __( 'Die exklusive Produktsperre ging nach dem Papierkorb-Vorgang verloren. Wiederhole ihn nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) );
		}
		wpagent_wc_forget_product_cache( $product_id );
		$post = get_post( $product_id );
		if ( true !== $trashed || ! $post instanceof WP_Post || 'trash' !== $post->post_status ) {
			return wpagent_wc_recovery_required( 'product', __( 'Das Produkt konnte nach dem Papierkorb-Vorgang nicht sicher als im Papierkorb verifiziert werden. Wiederhole ihn nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) );
		}
		return array( 'product_id' => $product_id, 'trashed' => true );
	} catch ( Throwable $error ) {
		return $delete_started
			? wpagent_wc_recovery_required( 'product', __( 'WooCommerce hat beim Produkt-Papierkorb-Vorgang einen Fehler ausgelöst. Wiederhole ihn nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ) )
			: new WP_Error( 'wpagent_wc_invalid', __( 'Das Produkt konnte nicht sicher für den Papierkorb vorbereitet werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	} finally {
		wpagent_wc_release_product_lock( $product_id, $lock );
	}
}

/**
 * @param WC_Product $product
 * @param array<string, mixed> $input
 * @return list<string>|WP_Error
 */
function wpagent_wc_apply_product_fields( WC_Product $product, array $input ) {
	$changed = array();
	if ( array_key_exists( 'sku', $input ) ) {
		$sku = (string) $input['sku'];
		$valid = wpagent_wc_validate_sku( $sku, $product->get_id() );
		if ( is_wp_error( $valid ) ) return $valid;
		$product->set_sku( $sku ); $changed[] = 'sku';
	}
	foreach ( array( 'regular_price', 'sale_price' ) as $field ) {
		if ( array_key_exists( $field, $input ) ) {
			$value = wpagent_sanitize_wc_price( $input[ $field ], $field );
			if ( is_wp_error( $value ) ) return $value;
			$product->{'set_' . $field}( $value ); $changed[] = $field;
		}
	}
	foreach ( array( 'weight', 'length', 'width', 'height' ) as $field ) {
		if ( array_key_exists( $field, $input ) ) {
			$value = wpagent_sanitize_wc_dimension( $input[ $field ], $field );
			if ( is_wp_error( $value ) ) return $value;
			$product->{'set_' . $field}( $value ); $changed[] = $field;
		}
	}
	foreach ( array( 'short_description', 'description' ) as $field ) if ( array_key_exists( $field, $input ) ) { $product->{'set_' . $field}( (string) $input[ $field ] ); $changed[] = $field; }
	foreach ( array( 'manage_stock', 'virtual', 'downloadable', 'featured' ) as $field ) if ( array_key_exists( $field, $input ) ) { $product->{'set_' . $field}( (bool) $input[ $field ] ); $changed[] = $field; }
	if ( array_key_exists( 'stock_quantity', $input ) ) { $product->set_stock_quantity( (int) $input['stock_quantity'] ); $changed[] = 'stock_quantity'; }
	if ( array_key_exists( 'stock_status', $input ) ) { $product->set_stock_status( (string) $input['stock_status'] ); $changed[] = 'stock_status'; }
	if ( array_key_exists( 'catalog_visibility', $input ) ) { $product->set_catalog_visibility( (string) $input['catalog_visibility'] ); $changed[] = 'catalog_visibility'; }
	if ( array_key_exists( 'image_id', $input ) ) {
		$image_id = (int) $input['image_id'];
		$valid = wpagent_wc_validate_image_id( $image_id, 'image_id' );
		if ( is_wp_error( $valid ) ) return $valid;
		$product->set_image_id( $image_id ); $changed[] = 'image_id';
	}
	if ( array_key_exists( 'gallery_image_ids', $input ) ) {
		$ids = array_values( array_unique( array_map( 'intval', (array) $input['gallery_image_ids'] ) ) );
		foreach ( $ids as $id ) {
			$valid = wpagent_wc_validate_image_id( $id, 'gallery_image_ids' );
			if ( is_wp_error( $valid ) || 0 === $id ) return is_wp_error( $valid ) ? $valid : new WP_Error( 'wpagent_bad_product_value', __( 'gallery_image_ids darf keine Null enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$product->set_gallery_image_ids( $ids ); $changed[] = 'gallery_image_ids';
	}
	$taxonomy_fields = array( 'category_ids' => 'product_cat', 'tag_ids' => 'product_tag' );
	foreach ( $taxonomy_fields as $field => $taxonomy ) {
		if ( ! array_key_exists( $field, $input ) ) continue;
		$allowed = wpagent_wc_require_assign_terms( $taxonomy );
		if ( is_wp_error( $allowed ) ) return $allowed;
		$ids = array_values( array_unique( array_map( 'intval', (array) $input[ $field ] ) ) );
		foreach ( $ids as $id ) if ( $id <= 0 || ! term_exists( $id, $taxonomy ) ) return new WP_Error( 'wpagent_bad_product_value', sprintf( /* translators: 1: ID, 2: Taxonomie. */ __( 'Term #%1$d existiert nicht in "%2$s".', 'wp-agent-companion' ), $id, $taxonomy ), array( 'status' => 400 ) );
		$product->{'set_' . $field}( $ids ); $changed[] = $field;
	}
	if ( array_key_exists( 'shipping_class_id', $input ) ) {
		$allowed = wpagent_wc_require_assign_terms( 'product_shipping_class' );
		if ( is_wp_error( $allowed ) ) return $allowed;
		$id = (int) $input['shipping_class_id'];
		if ( $id < 0 ) return new WP_Error( 'wpagent_bad_product_value', __( 'shipping_class_id darf nicht negativ sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		if ( $id > 0 && ! term_exists( $id, 'product_shipping_class' ) ) return new WP_Error( 'wpagent_bad_product_value', __( 'shipping_class_id muss auf eine vorhandene Versandklasse zeigen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		$product->set_shipping_class_id( $id ); $changed[] = 'shipping_class_id';
	}
	if ( array_key_exists( 'attributes', $input ) ) {
		$attributes = wpagent_wc_build_attributes( $input['attributes'] );
		if ( is_wp_error( $attributes ) ) return $attributes;
		$product->set_attributes( $attributes ); $changed[] = 'attributes';
	}
	return $changed;
}
