<?php
/**
 * CommerceBird MCP Abilities
 *
 * Registers WooCommerce MCP abilities for purchase orders and quotes via the
 * WordPress Abilities API (wp_register_ability / wp_abilities_api_init action).
 *
 * Abilities registered:
 *   - commercebird/create-purchase-order
 *   - commercebird/update-purchase-order
 *   - commercebird/delete-purchase-order
 *   - commercebird/create-quote
 *   - commercebird/update-quote
 *   - commercebird/delete-quote
 *
 * @package CommerceBird\Includes
 */
namespace CommerceBird;

defined( 'ABSPATH' ) || exit;

class CMBIRD_MCP {

	public static function init(): void {
		add_action( 'wp_abilities_api_init', array( __CLASS__, 'register_abilities' ) );
		add_filter( 'woocommerce_mcp_include_ability', array( __CLASS__, 'include_ability_in_mcp' ), 10, 2 );
	}

	public static function include_ability_in_mcp( bool $include, string $ability_id ): bool {
		if ( str_starts_with( $ability_id, 'commercebird/' ) ) {
			return true;
		}
		return $include;
	}

	public static function register_abilities(): void {
		if ( ! function_exists( 'wp_register_ability' ) ) {
			return;
		}
		wp_register_ability(
			'commercebird/create-purchase-order',
			array(
				'label'               => __( 'Create Purchase Order', 'commercebird' ),
				'category'            => 'site',
				'description'         => __( 'Creates a new purchase order (type: shop_purchase) with optional line items, status, and a note.', 'commercebird' ),
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'status'     => array(
							'type'        => 'string',
							'description' => 'Initial PO status (without wc- prefix).',
							'enum'        => array( 'awaiting-approval', 'approved', 'part-received', 'received' ),
							'default'     => 'awaiting-approval',
						),
						'line_items' => array(
							'type'        => 'array',
							'description' => 'Products to add to the purchase order.',
							'items'       => array(
								'type'       => 'object',
								'properties' => array(
									'product_id' => array(
										'type'        => 'integer',
										'description' => 'WooCommerce product ID.',
									),
									'quantity'   => array(
										'type'        => 'integer',
										'description' => 'Quantity to order.',
										'minimum'     => 1,
									),
									'price'      => array(
										'type'        => 'number',
										'description' => 'Unit cost price override. Defaults to the product price.',
									),
								),
								'required'   => array( 'product_id', 'quantity' ),
							),
						),
						'note'       => array(
							'type'        => 'string',
							'description' => 'Internal order note visible to admin.',
						),
					),
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'id'     => array(
							'type'        => 'integer',
							'description' => 'New purchase order ID.',
						),
						'status' => array( 'type' => 'string' ),
						'total'  => array(
							'type'        => 'string',
							'description' => 'Order total as a decimal string.',
						),
					),
					'required'   => array( 'id', 'status', 'total' ),
				),
				'execute_callback'    => array( __CLASS__, 'execute_create_purchase_order' ),
				'permission_callback' => array( __CLASS__, 'check_permission' ),
				'meta'                => array(
					'mcp'          => array( 'public' => true ),
					'show_in_rest' => true,
				),
			)
		);
		wp_register_ability(
			'commercebird/update-purchase-order',
			array(
				'label'               => __( 'Update Purchase Order', 'commercebird' ),
				'category'            => 'site',
				'description'         => __( 'Updates the status, line items, or notes of an existing purchase order. Providing line_items replaces all existing items.', 'commercebird' ),
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'id'         => array(
							'type'        => 'integer',
							'description' => 'ID of the purchase order to update.',
						),
						'status'     => array(
							'type'        => 'string',
							'description' => 'New PO status (without wc- prefix).',
							'enum'        => array( 'awaiting-approval', 'approved', 'part-received', 'received', 'cancelled' ),
						),
						'line_items' => array(
							'type'        => 'array',
							'description' => 'When provided, replaces all existing line items.',
							'items'       => array(
								'type'       => 'object',
								'properties' => array(
									'product_id' => array( 'type' => 'integer' ),
									'quantity'   => array(
										'type'    => 'integer',
										'minimum' => 1,
									),
									'price'      => array( 'type' => 'number' ),
								),
								'required'   => array( 'product_id', 'quantity' ),
							),
						),
						'note'       => array(
							'type'        => 'string',
							'description' => 'Internal order note to append.',
						),
					),
					'required'   => array( 'id' ),
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'id'     => array( 'type' => 'integer' ),
						'status' => array( 'type' => 'string' ),
						'total'  => array( 'type' => 'string' ),
					),
					'required'   => array( 'id', 'status', 'total' ),
				),
				'execute_callback'    => array( __CLASS__, 'execute_update_purchase_order' ),
				'permission_callback' => array( __CLASS__, 'check_permission' ),
				'meta'                => array( 'mcp' => array( 'public' => true ) ),
			)
		);
		wp_register_ability(
			'commercebird/delete-purchase-order',
			array(
				'label'               => __( 'Delete Purchase Order', 'commercebird' ),
				'category'            => 'site',
				'description'         => __( 'Moves a purchase order to trash.', 'commercebird' ),
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'id' => array(
							'type'        => 'integer',
							'description' => 'ID of the purchase order to delete.',
						),
					),
					'required'   => array( 'id' ),
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'deleted' => array( 'type' => 'boolean' ),
						'id'      => array( 'type' => 'integer' ),
					),
					'required'   => array( 'deleted', 'id' ),
				),
				'execute_callback'    => array( __CLASS__, 'execute_delete_purchase_order' ),
				'permission_callback' => array( __CLASS__, 'check_permission' ),
				'meta'                => array( 'mcp' => array( 'public' => true ) ),
			)
		);
		wp_register_ability(
			'commercebird/create-quote',
			array(
				'label'               => __( 'Create Quote', 'commercebird' ),
				'category'            => 'site',
				'description'         => __( 'Creates a new WooCommerce order with status on-quote. Advance it to quoted once pricing is finalised.', 'commercebird' ),
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'customer_id' => array(
							'type'        => 'integer',
							'description' => 'Existing WooCommerce customer user ID. Use 0 for guest.',
							'default'     => 0,
						),
						'line_items'  => array(
							'type'        => 'array',
							'description' => 'Products to include in the quote.',
							'items'       => array(
								'type'       => 'object',
								'properties' => array(
									'product_id' => array(
										'type'        => 'integer',
										'description' => 'WooCommerce product ID.',
									),
									'quantity'   => array(
										'type'    => 'integer',
										'minimum' => 1,
									),
									'price'      => array(
										'type'        => 'number',
										'description' => 'Unit price override.',
									),
								),
								'required'   => array( 'product_id', 'quantity' ),
							),
						),
						'note'        => array(
							'type'        => 'string',
							'description' => 'Internal note about this quote.',
						),
					),
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'id'       => array(
							'type'        => 'integer',
							'description' => 'New quote order ID.',
						),
						'status'   => array( 'type' => 'string' ),
						'total'    => array( 'type' => 'string' ),
						'validity' => array(
							'type'        => 'string',
							'description' => 'Quote validity date (Y-m-d H:i:s), empty if not yet set.',
						),
					),
					'required'   => array( 'id', 'status', 'total' ),
				),
				'execute_callback'    => array( __CLASS__, 'execute_create_quote' ),
				'permission_callback' => array( __CLASS__, 'check_permission' ),
				'meta'                => array( 'mcp' => array( 'public' => true ) ),
			)
		);
		wp_register_ability(
			'commercebird/update-quote',
			array(
				'label'               => __( 'Update Quote', 'commercebird' ),
				'category'            => 'site',
				'description'         => __( 'Updates status, line items, validity, or notes on a quote order (on-quote or quoted). Set status to quoted to formally send pricing to the customer.', 'commercebird' ),
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'id'            => array(
							'type'        => 'integer',
							'description' => 'ID of the quote order to update.',
						),
						'status'        => array(
							'type'        => 'string',
							'description' => 'New quote status (without wc- prefix).',
							'enum'        => array( 'on-quote', 'quoted', 'cancelled' ),
						),
						'line_items'    => array(
							'type'        => 'array',
							'description' => 'When provided, replaces all existing line items.',
							'items'       => array(
								'type'       => 'object',
								'properties' => array(
									'product_id' => array( 'type' => 'integer' ),
									'quantity'   => array(
										'type'    => 'integer',
										'minimum' => 1,
									),
									'price'      => array( 'type' => 'number' ),
								),
								'required'   => array( 'product_id', 'quantity' ),
							),
						),
						'validity_days' => array(
							'type'        => 'integer',
							'description' => 'Number of days from today the quote remains valid. Overwrites the existing validity date.',
							'minimum'     => 1,
						),
						'note'          => array(
							'type'        => 'string',
							'description' => 'Internal note to append.',
						),
					),
					'required'   => array( 'id' ),
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'id'       => array( 'type' => 'integer' ),
						'status'   => array( 'type' => 'string' ),
						'total'    => array( 'type' => 'string' ),
						'validity' => array( 'type' => 'string' ),
					),
					'required'   => array( 'id', 'status', 'total' ),
				),
				'execute_callback'    => array( __CLASS__, 'execute_update_quote' ),
				'permission_callback' => array( __CLASS__, 'check_permission' ),
				'meta'                => array( 'mcp' => array( 'public' => true ) ),
			)
		);
		wp_register_ability(
			'commercebird/delete-quote',
			array(
				'label'               => __( 'Delete Quote', 'commercebird' ),
				'category'            => 'site',
				'description'         => __( 'Moves a quote order (on-quote or quoted) to trash.', 'commercebird' ),
				'input_schema'        => array(
					'type'       => 'object',
					'properties' => array(
						'id' => array(
							'type'        => 'integer',
							'description' => 'ID of the quote order to delete.',
						),
					),
					'required'   => array( 'id' ),
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'deleted' => array( 'type' => 'boolean' ),
						'id'      => array( 'type' => 'integer' ),
					),
					'required'   => array( 'deleted', 'id' ),
				),
				'execute_callback'    => array( __CLASS__, 'execute_delete_quote' ),
				'permission_callback' => array( __CLASS__, 'check_permission' ),
				'meta'                => array( 'mcp' => array( 'public' => true ) ),
			)
		);
	}

	public static function check_permission(): bool {
		return current_user_can( 'manage_woocommerce' );
	}

	public static function execute_create_purchase_order( array $input ): array|\WP_Error {
		$allowed_statuses = array( 'awaiting-approval', 'approved', 'part-received', 'received' );
		$status           = $input['status'] ?? 'awaiting-approval';
		if ( ! in_array( $status, $allowed_statuses, true ) ) {
			return new \WP_Error( 'invalid_status', __( 'Invalid purchase order status.', 'commercebird' ) );
		}

		$order = new \CMBIRD_Purchase_Order();
		$order->set_status( 'wc-' . $status );

		foreach ( $input['line_items'] ?? array() as $item ) {
			$product = wc_get_product( (int) $item['product_id'] );
			if ( ! $product ) {
				continue;
			}
			$unit_price = isset( $item['price'] ) ? (float) $item['price'] : (float) $product->get_price();
			$qty        = max( 1, (int) $item['quantity'] );
			$order->add_product(
				$product,
				$qty,
				array(
					'subtotal' => $unit_price * $qty,
					'total'    => $unit_price * $qty,
				)
			);
		}

		$order->calculate_totals();
		$order->save();

		if ( ! $order->get_id() ) {
			return new \WP_Error( 'creation_failed', __( 'Failed to create purchase order.', 'commercebird' ) );
		}

		if ( ! empty( $input['note'] ) ) {
			$order->add_order_note( sanitize_textarea_field( $input['note'] ) );
		}

		return array(
			'id'     => $order->get_id(),
			'status' => $order->get_status(),
			'total'  => (string) $order->get_total(),
		);
	}

	public static function execute_update_purchase_order( array $input ): array|\WP_Error {
		$allowed_statuses = array( 'awaiting-approval', 'approved', 'part-received', 'received', 'cancelled' );

		if ( ! empty( $input['status'] ) && ! in_array( $input['status'], $allowed_statuses, true ) ) {
			return new \WP_Error( 'invalid_status', __( 'Invalid purchase order status.', 'commercebird' ) );
		}

		$order = wc_get_order( (int) $input['id'] );

		if ( ! $order || 'shop_purchase' !== $order->get_type() ) {
			return new \WP_Error( 'not_found', __( 'Purchase order not found.', 'commercebird' ) );
		}

		if ( ! empty( $input['status'] ) ) {
			$order->set_status( 'wc-' . $input['status'] );
		}

		if ( isset( $input['line_items'] ) ) {
			$order->remove_order_items( 'line_item' );
			foreach ( $input['line_items'] as $item ) {
				$product = wc_get_product( (int) $item['product_id'] );
				if ( ! $product ) {
					continue;
				}
				$unit_price = isset( $item['price'] ) ? (float) $item['price'] : (float) $product->get_price();
				$qty        = max( 1, (int) $item['quantity'] );
				$order->add_product(
					$product,
					$qty,
					array(
						'subtotal' => $unit_price * $qty,
						'total'    => $unit_price * $qty,
					)
				);
			}
			$order->calculate_totals();
		}

		$order->save();

		if ( ! empty( $input['note'] ) ) {
			$order->add_order_note( sanitize_textarea_field( $input['note'] ) );
		}

		return array(
			'id'     => $order->get_id(),
			'status' => $order->get_status(),
			'total'  => (string) $order->get_total(),
		);
	}

	public static function execute_delete_purchase_order( array $input ): array|\WP_Error {
		$order = wc_get_order( (int) $input['id'] );

		if ( ! $order || 'shop_purchase' !== $order->get_type() ) {
			return new \WP_Error( 'not_found', __( 'Purchase order not found.', 'commercebird' ) );
		}

		$id = $order->get_id();
		$order->delete();

		return array(
			'deleted' => true,
			'id'      => $id,
		);
	}

	public static function execute_update_quote( array $input ): array|\WP_Error {
		$allowed_statuses = array( 'on-quote', 'quoted', 'cancelled' );

		if ( ! empty( $input['status'] ) && ! in_array( $input['status'], $allowed_statuses, true ) ) {
			return new \WP_Error( 'invalid_status', __( 'Invalid quote status.', 'commercebird' ) );
		}

		$order = wc_get_order( (int) $input['id'] );

		if ( ! $order || ! in_array( $order->get_status(), array( 'on-quote', 'quoted' ), true ) ) {
			return new \WP_Error( 'not_found', __( 'Quote not found or not in a quote status.', 'commercebird' ) );
		}

		if ( ! empty( $input['status'] ) ) {
			$order->set_status( 'wc-' . $input['status'] );
		}

		if ( isset( $input['line_items'] ) ) {
			$order->remove_order_items( 'line_item' );
			foreach ( $input['line_items'] as $item ) {
				$product = wc_get_product( (int) $item['product_id'] );
				if ( ! $product ) {
					continue;
				}
				$unit_price = isset( $item['price'] ) ? (float) $item['price'] : (float) $product->get_price();
				$qty        = max( 1, (int) $item['quantity'] );
				$order->add_product(
					$product,
					$qty,
					array(
						'subtotal' => $unit_price * $qty,
						'total'    => $unit_price * $qty,
					)
				);
			}
			$order->calculate_totals();
		}

		if ( ! empty( $input['validity_days'] ) ) {
			$validity = gmdate( 'Y-m-d 23:59:59', strtotime( '+' . (int) $input['validity_days'] . ' days' ) );
			$order->update_meta_data( '_cmbird_quotation_validity', $validity );
		}

		$order->save();

		if ( ! empty( $input['note'] ) ) {
			$order->add_order_note( sanitize_textarea_field( $input['note'] ) );
		}

		return array(
			'id'       => $order->get_id(),
			'status'   => $order->get_status(),
			'total'    => (string) $order->get_total(),
			'validity' => (string) ( $order->get_meta( '_cmbird_quotation_validity' ) ?: '' ),
		);
	}

	public static function execute_delete_quote( array $input ): array|\WP_Error {
		$order = wc_get_order( (int) $input['id'] );

		if ( ! $order || ! in_array( $order->get_status(), array( 'on-quote', 'quoted' ), true ) ) {
			return new \WP_Error( 'not_found', __( 'Quote not found or not in a quote status.', 'commercebird' ) );
		}

		$id = $order->get_id();
		$order->delete();

		return array(
			'deleted' => true,
			'id'      => $id,
		);
	}

	public static function execute_create_quote( array $input ): array|\WP_Error {
		$order = wc_create_order(
			array(
				'customer_id' => (int) ( $input['customer_id'] ?? 0 ),
			)
		);

		if ( is_wp_error( $order ) ) {
			return $order;
		}

		$order->set_status( 'wc-on-quote' );

		foreach ( $input['line_items'] ?? array() as $item ) {
			$product = wc_get_product( (int) $item['product_id'] );
			if ( ! $product ) {
				continue;
			}
			$unit_price = isset( $item['price'] ) ? (float) $item['price'] : (float) $product->get_price();
			$qty        = max( 1, (int) $item['quantity'] );
			$order->add_product(
				$product,
				$qty,
				array(
					'subtotal' => $unit_price * $qty,
					'total'    => $unit_price * $qty,
				)
			);
		}

		$order->calculate_totals();
		$order->save();

		if ( ! $order->get_id() ) {
			return new \WP_Error( 'creation_failed', __( 'Failed to create quote.', 'commercebird' ) );
		}

		if ( ! empty( $input['note'] ) ) {
			$order->add_order_note( sanitize_textarea_field( $input['note'] ) );
		}

		return array(
			'id'       => $order->get_id(),
			'status'   => $order->get_status(),
			'total'    => (string) $order->get_total(),
			'validity' => (string) ( $order->get_meta( '_cmbird_quotation_validity' ) ?: '' ),
		);
	}
}
