<?php

namespace Antimanual\Tools;

use Antimanual\KnowledgeContextBuilder;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Built-in AI tool definitions for the Tool Registry.
 *
 * Read-only tools with an empty capability are safe for anonymous chatbot
 * visitors. Write tools require a capability and the caller's write flag.
 *
 * @package Antimanual
 */
class BuiltinTools {

	/**
	 * Return all built-in tool definitions.
	 *
	 * @return array<int, array>
	 */
	public static function definitions(): array {
		$tools = [
			[
				'name'         => 'search_knowledge_base',
				'title'        => __( 'Search knowledge base', 'antimanual' ),
				'description'  => 'Search the site\'s trained knowledge base and return the most relevant content for a query. Use this to answer questions about the site.',
				'capability'   => '',
				'read_only'    => true,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'query' => [ 'type' => 'string', 'description' => 'The search query or question.' ],
					],
					'required'   => [ 'query' ],
				],
				'callback'     => [ self::class, 'search_knowledge_base' ],
			],
			[
				'name'         => 'search_posts',
				'title'        => __( 'Search posts', 'antimanual' ),
				'description'  => 'Search published posts and pages by keyword. Returns titles, links, and excerpts.',
				'capability'   => '',
				'read_only'    => true,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'query'     => [ 'type' => 'string', 'description' => 'Keyword to search for.' ],
						'post_type' => [ 'type' => 'string', 'description' => 'Post type slug (e.g. post, page). Optional.' ],
						'limit'     => [ 'type' => 'integer', 'description' => 'Max results (1-20).', 'minimum' => 1, 'maximum' => 20 ],
					],
					'required'   => [ 'query' ],
				],
				'callback'     => [ self::class, 'search_posts' ],
			],
			[
				'name'         => 'get_post',
				'title'        => __( 'Get post', 'antimanual' ),
				'description'  => 'Get the full content of a single published post or page by its ID.',
				'capability'   => '',
				'read_only'    => true,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'id' => [ 'type' => 'integer', 'description' => 'The post ID.' ],
					],
					'required'   => [ 'id' ],
				],
				'callback'     => [ self::class, 'get_post' ],
			],
			[
				'name'         => 'list_recent_posts',
				'title'        => __( 'List recent posts', 'antimanual' ),
				'description'  => 'List the most recently published posts of a given type.',
				'capability'   => '',
				'read_only'    => true,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'post_type' => [ 'type' => 'string', 'description' => 'Post type slug. Defaults to post.' ],
						'limit'     => [ 'type' => 'integer', 'description' => 'Max results (1-20).', 'minimum' => 1, 'maximum' => 20 ],
					],
					'required'   => [],
				],
				'callback'     => [ self::class, 'list_recent_posts' ],
			],
			[
				'name'         => 'get_site_info',
				'title'        => __( 'Get site info', 'antimanual' ),
				'description'  => 'Get basic information about this WordPress site: name, description, URL, and content counts.',
				'capability'   => '',
				'read_only'    => true,
				'input_schema' => [ 'type' => 'object', 'properties' => [], 'required' => [] ],
				'callback'     => [ self::class, 'get_site_info' ],
			],
			[
				'name'         => 'create_post_draft',
				'title'        => __( 'Create draft post', 'antimanual' ),
				'description'  => 'Create a new draft post with a title and content. Returns the new post ID and edit link.',
				'capability'   => 'edit_posts',
				'read_only'    => false,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'title'   => [ 'type' => 'string', 'description' => 'Post title.' ],
						'content' => [ 'type' => 'string', 'description' => 'Post content (HTML or Gutenberg blocks).', 'atml_html' => true ],
						'excerpt' => [ 'type' => 'string', 'description' => 'Optional excerpt.' ],
					],
					'required'   => [ 'title', 'content' ],
				],
				'callback'     => [ self::class, 'create_post_draft' ],
			],
		];

		if ( class_exists( 'WooCommerce' ) ) {
			$tools[] = [
				'name'         => 'get_wc_product',
				'title'        => __( 'Get WooCommerce product', 'antimanual' ),
				'description'  => 'Look up a WooCommerce product by ID or search term. Returns name, price, stock status, and link.',
				'capability'   => '',
				'read_only'    => true,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'query' => [ 'type' => 'string', 'description' => 'Product name or keyword.' ],
						'id'    => [ 'type' => 'integer', 'description' => 'Product ID (optional, takes precedence).' ],
					],
					'required'   => [],
				],
				'callback'     => [ self::class, 'get_wc_product' ],
			];
			$tools[] = [
				'name'         => 'get_wc_order',
				'title'        => __( 'Get WooCommerce order', 'antimanual' ),
				'description'  => 'Look up a WooCommerce order by ID. Returns status, total, and line items.',
				'capability'   => 'manage_woocommerce',
				'read_only'    => true,
				'input_schema' => [
					'type'       => 'object',
					'properties' => [
						'order_id' => [ 'type' => 'integer', 'description' => 'The order ID.' ],
					],
					'required'   => [ 'order_id' ],
				],
				'callback'     => [ self::class, 'get_wc_order' ],
			];
		}

		return $tools;
	}

	// ─── Handlers ───────────────────────────────────────────────────────────────

	/**
	 * Search the knowledge base for a query.
	 *
	 * @param array $args Arguments.
	 * @return array
	 */
	public static function search_knowledge_base( array $args ): array {
		$query   = (string) ( $args['query'] ?? '' );
		$context = KnowledgeContextBuilder::build_context( [], $query );

		return [
			'query'   => $query,
			'context' => '' !== $context ? $context : __( 'No relevant knowledge base content was found.', 'antimanual' ),
		];
	}

	/**
	 * Search published posts/pages by keyword.
	 *
	 * @param array $args Arguments.
	 * @return array
	 */
	public static function search_posts( array $args ): array {
		$post_type = sanitize_key( (string) ( $args['post_type'] ?? '' ) );
		$limit     = isset( $args['limit'] ) ? min( 20, max( 1, (int) $args['limit'] ) ) : 5;

		$query_args = [
			'post_type'        => $post_type && post_type_exists( $post_type ) ? $post_type : [ 'post', 'page' ],
			'post_status'      => 'publish',
			's'                => (string) ( $args['query'] ?? '' ),
			'posts_per_page'   => $limit,
			'no_found_rows'    => true,
			'suppress_filters' => false,
		];

		$results = [];
		foreach ( get_posts( $query_args ) as $post ) {
			$results[] = [
				'id'      => $post->ID,
				'title'   => get_the_title( $post ),
				'url'     => get_permalink( $post ),
				'type'    => $post->post_type,
				'excerpt' => wp_trim_words( wp_strip_all_tags( $post->post_content ), 40 ),
			];
		}

		return [ 'count' => count( $results ), 'results' => $results ];
	}

	/**
	 * Get a single published post by ID.
	 *
	 * @param array $args Arguments.
	 * @return array|\WP_Error
	 */
	public static function get_post( array $args ) {
		$post = get_post( (int) ( $args['id'] ?? 0 ) );

		if ( ! $post || 'publish' !== $post->post_status ) {
			return new \WP_Error( 'not_found', __( 'Post not found.', 'antimanual' ), [ 'status' => 404 ] );
		}

		return [
			'id'      => $post->ID,
			'title'   => get_the_title( $post ),
			'url'     => get_permalink( $post ),
			'type'    => $post->post_type,
			'content' => wp_strip_all_tags( $post->post_content ),
		];
	}

	/**
	 * List recent published posts of a type.
	 *
	 * @param array $args Arguments.
	 * @return array
	 */
	public static function list_recent_posts( array $args ): array {
		$post_type = sanitize_key( (string) ( $args['post_type'] ?? 'post' ) );
		$limit     = isset( $args['limit'] ) ? min( 20, max( 1, (int) $args['limit'] ) ) : 10;

		$results = [];
		foreach ( get_posts( [
			'post_type'      => post_type_exists( $post_type ) ? $post_type : 'post',
			'post_status'    => 'publish',
			'posts_per_page' => $limit,
			'no_found_rows'  => true,
		] ) as $post ) {
			$results[] = [
				'id'    => $post->ID,
				'title' => get_the_title( $post ),
				'url'   => get_permalink( $post ),
				'date'  => get_the_date( 'c', $post ),
			];
		}

		return [ 'count' => count( $results ), 'results' => $results ];
	}

	/**
	 * Get basic site information.
	 *
	 * @return array
	 */
	public static function get_site_info(): array {
		return [
			'name'        => get_bloginfo( 'name' ),
			'description' => get_bloginfo( 'description' ),
			'url'         => home_url(),
			'language'    => get_bloginfo( 'language' ),
			'posts'       => (int) wp_count_posts( 'post' )->publish,
			'pages'       => (int) wp_count_posts( 'page' )->publish,
		];
	}

	/**
	 * Create a draft post.
	 *
	 * @param array $args Arguments.
	 * @return array|\WP_Error
	 */
	public static function create_post_draft( array $args ) {
		$post_id = wp_insert_post(
			[
				'post_title'   => sanitize_text_field( (string) ( $args['title'] ?? '' ) ),
				'post_content' => (string) ( $args['content'] ?? '' ),
				'post_excerpt' => sanitize_textarea_field( (string) ( $args['excerpt'] ?? '' ) ),
				'post_status'  => 'draft',
				'post_type'    => 'post',
			],
			true
		);

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

		return [
			'id'       => (int) $post_id,
			'status'   => 'draft',
			'edit_url' => get_edit_post_link( $post_id, 'raw' ),
		];
	}

	/**
	 * Look up a WooCommerce product.
	 *
	 * @param array $args Arguments.
	 * @return array|\WP_Error
	 */
	public static function get_wc_product( array $args ) {
		if ( ! function_exists( 'wc_get_product' ) ) {
			return new \WP_Error( 'wc_inactive', __( 'WooCommerce is not active.', 'antimanual' ), [ 'status' => 400 ] );
		}

		$id = (int) ( $args['id'] ?? 0 );

		if ( ! $id ) {
			$found = get_posts( [
				'post_type'      => 'product',
				'post_status'    => 'publish',
				's'              => (string) ( $args['query'] ?? '' ),
				'posts_per_page' => 1,
				'no_found_rows'  => true,
				'fields'         => 'ids',
			] );
			$id    = $found[0] ?? 0;
		}

		$product = $id ? wc_get_product( $id ) : null;

		if ( ! $product ) {
			return new \WP_Error( 'not_found', __( 'Product not found.', 'antimanual' ), [ 'status' => 404 ] );
		}

		return [
			'id'           => $product->get_id(),
			'name'         => $product->get_name(),
			'price'        => wp_strip_all_tags( wc_price( $product->get_price() ) ),
			'stock_status' => $product->get_stock_status(),
			'url'          => get_permalink( $product->get_id() ),
		];
	}

	/**
	 * Look up a WooCommerce order (privileged).
	 *
	 * @param array $args Arguments.
	 * @return array|\WP_Error
	 */
	public static function get_wc_order( array $args ) {
		if ( ! function_exists( 'wc_get_order' ) ) {
			return new \WP_Error( 'wc_inactive', __( 'WooCommerce is not active.', 'antimanual' ), [ 'status' => 400 ] );
		}

		$order = wc_get_order( (int) ( $args['order_id'] ?? 0 ) );

		if ( ! $order ) {
			return new \WP_Error( 'not_found', __( 'Order not found.', 'antimanual' ), [ 'status' => 404 ] );
		}

		$items = [];
		foreach ( $order->get_items() as $item ) {
			$items[] = [
				'name'     => $item->get_name(),
				'quantity' => $item->get_quantity(),
			];
		}

		return [
			'id'     => $order->get_id(),
			'status' => $order->get_status(),
			'total'  => wp_strip_all_tags( wc_price( $order->get_total() ) ),
			'items'  => $items,
		];
	}
}
