<?php
/**
 * Workflow State REST API Controller
 *
 * Provides REST API endpoints for workflow activation/deactivation.
 *
 * @package Sequensy
 * @since 2.0.0
 */

declare(strict_types=1);

namespace Sequensy\Rest;

use Sequensy\Container;
use Sequensy\Storage\WorkflowStorage;
use Sequensy\Triggers\TriggerRegistry;
use Sequensy\Actions\ActionRegistry;
use Sequensy\Validation\WorkflowValidator;
use WP_REST_Controller;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Class WorkflowStateController
 *
 * REST API controller for workflow state management (activate/deactivate).
 */
class WorkflowStateController extends WP_REST_Controller {

	use RestControllerTrait;

	/**
	 * Workflow storage instance.
	 *
	 * @var WorkflowStorage
	 */
	private WorkflowStorage $storage;

	/**
	 * Trigger registry instance.
	 *
	 * @var TriggerRegistry
	 */
	private TriggerRegistry $trigger_registry;

	/**
	 * Action registry instance.
	 *
	 * @var ActionRegistry
	 */
	private ActionRegistry $action_registry;

	/**
	 * Factory method for creating controller instance with container.
	 *
	 * @param Container $container Service container instance.
	 * @return self Controller instance.
	 */
	public static function create( Container $container ): self {
		return new self(
			$container->get( 'workflow_storage' ),
			$container->get( 'trigger_registry' ),
			$container->get( 'action_registry' )
		);
	}

	/**
	 * Constructor.
	 *
	 * @param WorkflowStorage|null $storage          Optional storage instance.
	 * @param TriggerRegistry|null $trigger_registry Optional trigger registry.
	 * @param ActionRegistry|null  $action_registry  Optional action registry.
	 */
	public function __construct(
		?WorkflowStorage $storage = null,
		?TriggerRegistry $trigger_registry = null,
		?ActionRegistry $action_registry = null
	) {
		$this->namespace = 'sequensy/v1';

		// Use provided dependencies or get from container.
		$container              = Container::getInstance();
		$this->storage          = $storage ?? $container->get( 'workflow_storage' );
		$this->trigger_registry = $trigger_registry ?? $container->get( 'trigger_registry' );
		$this->action_registry  = $action_registry ?? $container->get( 'action_registry' );
	}

	/**
	 * Register REST API routes.
	 */
	public function register_routes(): void {
		// Activate workflow.
		register_rest_route(
			$this->namespace,
			'/workflows/(?P<id>[\d]+)/activate',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'activate_item' ),
				'permission_callback' => array( $this, 'permissions_check' ),
				'args'                => array(
					'id' => array(
						'description'       => 'Workflow ID',
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
						'validate_callback' => 'rest_validate_request_arg',
					),
				),
			)
		);

		// Deactivate workflow.
		register_rest_route(
			$this->namespace,
			'/workflows/(?P<id>[\d]+)/deactivate',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'deactivate_item' ),
				'permission_callback' => array( $this, 'permissions_check' ),
				'args'                => array(
					'id' => array(
						'description'       => 'Workflow ID',
						'type'              => 'integer',
						'required'          => true,
						'sanitize_callback' => 'absint',
						'validate_callback' => 'rest_validate_request_arg',
					),
				),
			)
		);
	}

	/**
	 * Activate a workflow.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object.
	 */
	public function activate_item( WP_REST_Request $request ): WP_REST_Response|WP_Error {
		$workflow = $this->storage->get_workflow( (int) $request['id'] );

		if ( ! $workflow ) {
			return $this->rest_error(
				'not_found',
				__( 'Workflow not found', 'sequensy' ),
				404
			);
		}

		// Require workflow to be published before activation.
		if ( ! $workflow->published_version_id ) {
			return $this->rest_error(
				'not_published',
				__( 'Workflow must be published before it can be activated.', 'sequensy' ),
				400,
				array(
					'errors' => array(
						array(
							'code'    => 'not_published',
							'message' => __( 'Please publish your workflow first.', 'sequensy' ),
						),
					),
				)
			);
		}

		// Run comprehensive validation before activation.
		$validator  = new WorkflowValidator( $this->trigger_registry, $this->action_registry );
		$validation = $validator->validate_for_activation( $workflow );

		if ( ! $validation['valid'] ) {
			return $this->rest_error(
				'validation_failed',
				__( 'Workflow cannot be activated due to configuration errors.', 'sequensy' ),
				400,
				array( 'errors' => $validation['errors'] )
			);
		}

		$result = $this->storage->activate_workflow( (int) $request['id'] );

		if ( ! $result ) {
			return $this->rest_error(
				'activation_failed',
				__( 'Failed to activate workflow', 'sequensy' ),
				500
			);
		}

		$workflow = $this->storage->get_workflow( (int) $request['id'] );

		return rest_ensure_response( $workflow );
	}

	/**
	 * Deactivate a workflow.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object.
	 */
	public function deactivate_item( WP_REST_Request $request ): WP_REST_Response|WP_Error {
		$workflow = $this->storage->get_workflow( (int) $request['id'] );

		if ( ! $workflow ) {
			return $this->rest_error(
				'not_found',
				__( 'Workflow not found', 'sequensy' ),
				404
			);
		}

		$result = $this->storage->deactivate_workflow( (int) $request['id'] );

		if ( ! $result ) {
			return $this->rest_error(
				'deactivation_failed',
				__( 'Failed to deactivate workflow', 'sequensy' ),
				500
			);
		}

		$workflow = $this->storage->get_workflow( (int) $request['id'] );

		return rest_ensure_response( $workflow );
	}
}
