<?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' ),
				'sku' => array( 'type' => 'string' ),
				'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 ),
				'per_page' => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => 100 ),
			),
		),
		'output_schema' => array( 'type' => 'object', 'properties' => array( 'products' => array( 'type' => 'array' ), 'total' => array( 'type' => 'integer' ), 'pages' => array( 'type' => 'integer' ) ) ),
		'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' ),
		),
		'output_schema' => array( 'type' => 'object', 'properties' => array( 'product' => array( 'type' => 'object' ), 'verified' => array( 'type' => 'boolean' ) ) ),
		'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 endgültig löschen', 'wp-agent-companion' ),
		'description' => __( 'Löscht ein WooCommerce-Produkt einschließlich seiner Varianten endgültig. confirm=true ist zwingend erforderlich.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'properties' => array( 'product_id' => array( 'type' => 'integer' ), 'confirm' => array( 'type' => 'boolean' ) ), 'required' => array( 'product_id', 'confirm' ) ),
		'output_schema' => array( 'type' => 'object', 'properties' => array( 'product_id' => array( 'type' => 'integer' ), 'deleted' => 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' ),
		'status' => array( 'type' => 'string', 'enum' => array( 'draft', 'publish', 'pending', 'private' ) ),
		'sku' => array( 'type' => 'string' ),
		'regular_price' => array( 'type' => 'string' ),
		'sale_price' => array( 'type' => 'string' ),
		'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' ),
		'description' => array( 'type' => 'string' ),
		'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' ),
		'length' => array( 'type' => 'string' ),
		'width' => array( 'type' => 'string' ),
		'height' => array( 'type' => 'string' ),
		'image_id' => array( 'type' => 'integer', 'minimum' => 0 ),
		'gallery_image_ids' => array( 'type' => 'array', 'items' => array( 'type' => 'integer', 'minimum' => 1 ) ),
		'category_ids' => array( 'type' => 'array', 'items' => array( 'type' => 'integer', 'minimum' => 1 ) ),
		'tag_ids' => array( 'type' => 'array', 'items' => array( 'type' => 'integer', 'minimum' => 1 ) ),
		'shipping_class_id' => array( 'type' => 'integer', 'minimum' => 0 ),
		'attributes' => array( 'type' => 'array', 'items' => array( 'type' => 'object' ) ),
	);
	if ( $include_id ) {
		$properties = array( 'product_id' => array( 'type' => 'integer' ) ) + $properties;
	}
	return $properties;
}

/** @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 ) );

	$page = max( 1, (int) ( $input['page'] ?? 1 ) );
	$limit = min( 100, max( 1, (int) ( $input['per_page'] ?? 20 ) ) );
	$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' );
		$ids = $data_store->search_products( trim( (string) $input['search'] ), '', false, true, 1000 );
		if ( array() === $ids ) return array( 'products' => array(), 'total' => 0, 'pages' => 0 );
		$args['include'] = array_map( 'intval', $ids );
	}
	$query = new WC_Product_Query( $args );
	$result = $query->get_products();
	return array(
		'products' => array_map( 'wpagent_wc_product_payload', $result->products ),
		'total' => (int) $result->total,
		'pages' => (int) $result->max_num_pages,
	);
}

/** @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;
	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 ) ) ) );
		$product_id = $product->save();
	} catch ( WC_Data_Exception $e ) {
		return new WP_Error( 'wpagent_wc_invalid', $e->getMessage(), array( 'status' => 400 ) );
	}
	$fresh = wc_get_product( $product_id );
	if ( ! $fresh instanceof WC_Product ) {
		return new WP_Error( 'wpagent_wc_readback_failed', __( 'Das erstellte Produkt konnte nicht erneut gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$verification = wpagent_wc_verify_product_fields( $fresh, $expected );
	return array( 'product' => wpagent_wc_product_payload( $fresh ), 'verified' => $verification['verified'] );
}

/** @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['confirm'] ?? false ) ) return new WP_Error( 'wpagent_confirmation_required', __( 'Zum endgültigen Löschen ist confirm=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$deleted = $product->delete( true );
	wc_delete_product_transients( $product_id );
	clean_post_cache( $product_id );
	return array( 'product_id' => $product_id, 'deleted' => true === $deleted && null === get_post( $product_id ) );
}

/**
 * @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;
}
