<?php

namespace Limb_Chatbot\Includes\Api\V1\Controllers;

use Exception;
use Limb_Chatbot\Includes\Data_Objects\Action;
use Limb_Chatbot\Includes\Data_Objects\Action_Submission;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Repositories\Action_Submission_Repository;
use Limb_Chatbot\Includes\Services\Helper;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;

/**
 * Controller for managing Action Submissions via REST API.
 *
 * Provides endpoints for retrieving action submission records:
 * - GET /actions/{action_id}/submissions - List all submissions for an action
 * - GET /actions/{action_id}/submissions/{id} - Get a single submission
 *
 * @package Limb_Chatbot\Includes\Api\V1\Controllers
 * @since 1.0.0
 */
class Action_Submissions_Controller extends Rest_Controller {

	/**
	 * REST route base.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	protected $rest_base = 'actions/(?P<action_id>[\d]+)/submissions';

	/**
	 * Action Submission repository instance.
	 *
	 * @var Action_Submission_Repository
	 * @since 1.0.0
	 */
	protected Action_Submission_Repository $repository;

	/**
	 * Action_Submissions_Controller constructor.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		$this->repository = new Action_Submission_Repository();
	}

	/**
	 * Registers REST routes for action submissions.
	 *
	 * Defines routes for retrieving submission records.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function register_routes() {
		// GET /actions/{action_id}/submissions - List all submissions for an action
		register_rest_route( $this->namespace, '/' . $this->rest_base, array(
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_items' ),
				'permission_callback' => array( $this, 'permission_callback' ),
				'args'                => $this->get_action_id_arg(),
			),
			'schema' => array( $this, 'get_item_schema' ),
		) );

		// GET /actions/{action_id}/submissions/{id} - Get single submission
		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_item' ),
				'permission_callback' => array( $this, 'permission_callback' ),
				'args'                => array(
					'id' => array(
						'required'          => true,
						'validate_callback' => function ( $value ) {
							return ! empty( Action_Submission::find( $value ) );
						},
					),
				),
			),
			'schema' => array( $this, 'get_item_schema' ),
		) );
	}

	/**
	 * Returns validation arguments for action_id parameter.
	 *
	 * @return array
	 * @since 1.0.0
	 */
	private function get_action_id_arg(): array {
		return array(
			'action_id' => array(
				'description'       => __( 'Filter submissions by associated action ID.', 'limb-chatbot' ),
				'type'              => 'integer',
				'required'          => true,
				'sanitize_callback' => 'absint',
				'validate_callback' => function ( $value ) {
					return ! empty( Action::find( $value ) );
				},
			),
			'per_page'  => array(
				'description'       => __( 'Maximum number of submissions to return per page.', 'limb-chatbot' ),
				'type'              => 'integer',
				'default'           => 10,
				'sanitize_callback' => 'absint',
			),
			'page'      => array(
				'description'       => __( 'The page number of the results in paginated set.', 'limb-chatbot' ),
				'type'              => 'integer',
				'default'           => 1,
				'sanitize_callback' => 'absint',
			),
			'orderby'   => array(
				'description'       => __( 'Sort collection by field.', 'limb-chatbot' ),
				'type'              => 'string',
				'default'           => 'created_at',
				'enum'              => [ 'id', 'status', 'created_at' ],
				'sanitize_callback' => 'sanitize_key',
			),
			'order'     => array(
				'description'       => __( 'Order sort attribute ascending or descending.', 'limb-chatbot' ),
				'type'              => 'string',
				'default'           => 'DESC',
				'enum'              => [ 'ASC', 'DESC' ],
				'sanitize_callback' => 'sanitize_key',
			),
			'search'    => array(
				'description'       => __( 'Limit results to those matching a string.', 'limb-chatbot' ),
				'type'              => 'string',
				'sanitize_callback' => 'sanitize_text_field',
			),
		);
	}

	/**
	 * Returns a collection of action submission items for a specific action.
	 *
	 * @param  WP_REST_Request  $request  REST request object.
	 *
	 * @return WP_REST_Response|WP_Error
	 * @since 1.0.0
	 */
	public function get_items( $request ) {
		try {
			$action_id = $request->get_param( 'action_id' );

			// Get submissions using repository with search and pagination support
			$items = $this->repository->get_items( $action_id, $request->get_query_params() );

			return rest_ensure_response( $this->prepare_collection($items, $request) );
		} catch ( Exception $e ) {
			Helper::log( $e, __METHOD__ );

			return Helper::get_wp_error( $e );
		}
	}

	/**
	 * Returns a single action submission item.
	 *
	 * @param  WP_REST_Request  $request  REST request object.
	 *
	 * @return WP_REST_Response|WP_Error
	 * @since 1.0.0
	 */
	public function get_item( $request ) {
		try {
			$id = $request->get_param( 'id' );

			$submission = Action_Submission::find( $id );

			if ( ! $submission ) {
				throw new Exception(
					__( 'Action submission not found', 'limb-chatbot' ),
					Error_Codes::NOT_FOUND
				);
			}

			return rest_ensure_response( $submission );
		} catch ( Exception $e ) {
			Helper::log( $e, __METHOD__ );

			return Helper::get_wp_error( $e );
		}
	}

	/**
	 * Get schema for the item.
	 *
	 * @return array
	 * @since 1.0.0
	 */
	public function get_item_schema() {
		return [
			'type'       => 'object',
			'properties' => [
				'id'               => [
					'type'        => 'integer',
					'description' => __( 'Submission ID', 'limb-chatbot' ),
				],
				'action_id'        => [
					'type'        => 'integer',
					'description' => __( 'Associated action ID', 'limb-chatbot' ),
				],
				'action_data'      => [
					'type'        => 'object',
					'description' => __( 'Collected action data', 'limb-chatbot' ),
				],
				'chatbot_user_id'  => [
					'type'        => 'integer',
					'description' => __( 'Chatbot user who submitted', 'limb-chatbot' ),
				],
				'chat_uuid'        => [
					'type'        => 'string',
					'description' => __( 'Associated chat UUID', 'limb-chatbot' ),
				],
				'callback_results' => [
					'type'        => 'object',
					'description' => __( 'Results from executed callbacks', 'limb-chatbot' ),
				],
				'extracted_vars'   => [
					'type'        => 'object',
					'description' => __( 'Variables extracted from callbacks', 'limb-chatbot' ),
				],
				'status'           => [
					'type'        => 'string',
					'enum'        => [ 'pending', 'success', 'failed' ],
					'description' => __( 'Submission status', 'limb-chatbot' ),
				],
				'error_message'    => [
					'type'        => 'string',
					'description' => __( 'Error message if submission failed', 'limb-chatbot' ),
				],
				'created_at'       => [
					'type'        => 'string',
					'format'      => 'date-time',
					'description' => __( 'When the submission was created', 'limb-chatbot' ),
				],
			],
		];
	}
}
