<?php
/** Verified write abilities for WooCommerce global product attributes. */

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

function wpagent_ability_upsert_product_attribute(): array {
	return array(
		'label'               => __( 'Globales Produktattribut anlegen oder aktualisieren', 'wp-agent-companion' ),
		'description'         => __( 'Schreibt ein WooCommerce-Produktattribut über die öffentliche API mit Sperre, Konfliktschutz, Read-back und verifiziertem Rollback.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'attribute_id'       => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'name'               => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ),
				'slug'               => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 31 ),
				'type'               => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 64 ),
				'order_by'           => array( 'type' => 'string', 'enum' => array( 'menu_order', 'name', 'name_num', 'id' ) ),
				'has_archives'       => array( 'type' => 'boolean' ),
			),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'attribute' => wpagent_wc_attribute_schema(),
				'created'   => array( 'type' => 'boolean' ),
				'verified'  => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'attribute', 'created', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_upsert_product_attribute',
		'permission_callback' => 'wpagent_perm_wc_manage_product_terms',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return WP_Error */
function wpagent_wc_attribute_rollback_error( ?array $previous, int $created_id = 0 ) {
	$verified = false;
	try {
		if ( null === $previous ) {
			if ( $created_id > 0 ) {
				wc_delete_attribute( $created_id );
			}
			$verified = $created_id <= 0 || null === wpagent_wc_attribute_record( $created_id );
		} else {
			$result = wc_update_attribute( (int) $previous['attribute_id'], wpagent_wc_attribute_provider_args( $previous ) );
			$fresh  = is_wp_error( $result ) ? null : wpagent_wc_attribute_record( (int) $previous['attribute_id'] );
			$verified = $fresh && hash_equals( $previous['state_hash'], wpagent_wc_attribute_payload( $fresh )['state_hash'] );
		}
	} catch ( Throwable $error ) {
		$verified = false;
	}
	if ( ! $verified ) {
		return new WP_Error( 'wpagent_wc_attribute_rollback_unverified', __( 'Das WooCommerce-Attribut-Rollback konnte nicht verifiziert werden. Prüfe die Produktattribute sofort manuell.', 'wp-agent-companion' ), array( 'status' => 500, 'rollback_verified' => false ) );
	}
	return new WP_Error( 'wpagent_wc_attribute_write_unverified', __( 'WooCommerce hat das Produktattribut nicht exakt bestätigt. Der vorherige Zustand wurde verifiziert wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 502, 'rollback_verified' => true ) );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_upsert_product_attribute( $input ) {
	$input     = is_array( $input ) ? $input : array();
	$available = wpagent_wc_require_attribute_runtime();
	if ( is_wp_error( $available ) ) {
		return $available;
	}
	$attribute_id = absint( $input['attribute_id'] ?? 0 );
	$creating     = 0 === $attribute_id;
	$lock         = wpagent_wc_attribute_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$record   = $creating ? null : wpagent_wc_attribute_record( $attribute_id );
		$previous = $record ? wpagent_wc_attribute_payload( $record ) : null;
		if ( ! $creating && ! $previous ) {
			return new WP_Error( 'wpagent_wc_attribute_not_found', __( 'Globales WooCommerce-Produktattribut nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		if ( ! $creating ) {
			$expected_hash = strtolower( (string) ( $input['expected_state_hash'] ?? '' ) );
			if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) || ! hash_equals( $previous['state_hash'], $expected_hash ) ) {
				return new WP_Error( 'wpagent_wc_attribute_conflict', __( 'Das Produktattribut hat sich seit dem Lesen geändert. Lies es neu und wiederhole den Vorgang.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $previous['state_hash'] ) );
			}
		}
		$next = wpagent_wc_validate_attribute_fields( $input, $creating, $previous );
		if ( is_wp_error( $next ) ) {
			return $next;
		}
		try {
			$result = $creating ? wc_create_attribute( $next ) : wc_update_attribute( $attribute_id, $next );
		} catch ( Throwable $error ) {
			if ( $creating ) {
				$attribute_id = wpagent_wc_attribute_id_by_slug( $next['slug'] );
			}
			return wpagent_wc_attribute_rollback_error( $previous, $attribute_id );
		}
		if ( is_wp_error( $result ) ) {
			return $result;
		}
		$attribute_id = absint( $result );
		$fresh_record = wpagent_wc_attribute_record( $attribute_id );
		if ( ! $fresh_record ) {
			return wpagent_wc_attribute_rollback_error( $previous, $attribute_id );
		}
		$fresh    = wpagent_wc_attribute_payload( $fresh_record );
		$expected = array_merge( array( 'attribute_id' => $attribute_id ), $next );
		foreach ( array( 'attribute_id', 'name', 'slug', 'type', 'order_by', 'has_archives' ) as $field ) {
			if ( $fresh[ $field ] !== $expected[ $field ] ) {
				return wpagent_wc_attribute_rollback_error( $previous, $attribute_id );
			}
		}
		return array( 'attribute' => $fresh, 'created' => $creating, 'verified' => true );
	} finally {
		wpagent_wc_attribute_release_lock( $lock );
	}
}

function wpagent_ability_delete_product_attribute(): array {
	return array(
		'label'               => __( 'Globales Produktattribut löschen', 'wp-agent-companion' ),
		'description'         => __( 'Löscht ein globales WooCommerce-Produktattribut samt zugehörigen Termen erst nach Konflikt- und doppelter Bestätigungsprüfung.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'attribute_id'       => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'confirm'            => array( 'type' => 'boolean' ),
				'confirm_data_loss'  => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'attribute_id', 'expected_state_hash', 'confirm', 'confirm_data_loss' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'attribute_id' => array( 'type' => 'integer' ),
				'deleted'      => array( 'type' => 'boolean' ),
				'verified'     => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'attribute_id', 'deleted', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_delete_product_attribute',
		'permission_callback' => 'wpagent_perm_wc_manage_product_terms',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_delete_product_attribute( $input ) {
	$input = is_array( $input ) ? $input : array();
	if ( ! rest_sanitize_boolean( $input['confirm'] ?? false ) ) {
		return new WP_Error( 'wpagent_confirmation_required', __( 'Zum Löschen ist confirm=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( ! rest_sanitize_boolean( $input['confirm_data_loss'] ?? false ) ) {
		return new WP_Error( 'wpagent_wc_attribute_data_loss_confirmation_required', __( 'Das Löschen entfernt auch alle Attributwerte. Bestätige diesen Datenverlust ausdrücklich mit confirm_data_loss=true.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$available = wpagent_wc_require_attribute_runtime();
	if ( is_wp_error( $available ) ) {
		return $available;
	}
	$attribute_id = absint( $input['attribute_id'] ?? 0 );
	$lock = wpagent_wc_attribute_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$record = wpagent_wc_attribute_record( $attribute_id );
		if ( ! $record ) {
			return new WP_Error( 'wpagent_wc_attribute_not_found', __( 'Globales WooCommerce-Produktattribut nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		$current       = wpagent_wc_attribute_payload( $record );
		$expected_hash = strtolower( (string) ( $input['expected_state_hash'] ?? '' ) );
		if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) || ! hash_equals( $current['state_hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_wc_attribute_conflict', __( 'Das Produktattribut hat sich seit dem Lesen geändert. Lies es neu und wiederhole den Vorgang.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['state_hash'] ) );
		}
		try {
			$deleted = wc_delete_attribute( $attribute_id );
		} catch ( Throwable $error ) {
			$deleted = false;
		}
		// A provider hook can abort before WooCommerce invalidates its attribute
		// cache. Refresh explicitly and verify both the definition and the terms
		// because wc_delete_attribute() ignores individual wp_delete_term() errors.
		wpagent_wc_refresh_attribute_cache();
		$definition_deleted = null === wpagent_wc_attribute_record( $attribute_id );
		$term_counts        = wpagent_wc_attribute_term_counts( array( $current['taxonomy'] ) );
		$remaining_terms    = $term_counts[ $current['taxonomy'] ] ?? 0;
		$verified           = $definition_deleted && 0 === $remaining_terms;
		if ( ! $verified ) {
			return new WP_Error(
				'wpagent_wc_attribute_delete_unverified',
				__( 'WooCommerce konnte das Produktattribut nicht verifiziert löschen.', 'wp-agent-companion' ),
				array(
					'status'               => 502,
					'definition_deleted'   => $definition_deleted,
					'remaining_term_count' => $remaining_terms,
				)
			);
		}
		return array( 'attribute_id' => $attribute_id, 'deleted' => (bool) $deleted || $verified, 'verified' => true );
	} finally {
		wpagent_wc_attribute_release_lock( $lock );
	}
}
