<?php
namespace WpRigel\Commandify;

defined( 'ABSPATH' ) || exit;

class RestApi {

	private static $namespace = 'commandify/v1';

	public static function init() {
		add_action( 'rest_api_init', array( __CLASS__, 'register_routes' ) );
	}

	public static function register_routes() {
		// Note: /commands and /search endpoints removed - commands now passed via wp_localize_script

		// POST execute.
		register_rest_route(
			self::$namespace,
			'/execute',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'execute_command' ),
				'permission_callback' => array( __CLASS__, 'verify_nonce' ),
				'args'                => array(
					'command_id' => array(
						'required'          => true,
						'sanitize_callback' => 'sanitize_key',
					),
				),
			)
		);

		// GET user preferences.
		register_rest_route(
			self::$namespace,
			'/preferences',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_preferences' ),
				'permission_callback' => function () {
					return is_user_logged_in();
				},
			)
		);

		// POST update preferences.
		register_rest_route(
			self::$namespace,
			'/preferences',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'update_preferences' ),
				'permission_callback' => array( __CLASS__, 'verify_nonce' ),
				'args'                => array(
					'preferences' => array(
						'required' => true,
						'type'     => 'object',
					),
				),
			)
		);
	}

	// Removed get_commands() and search_commands() - commands now passed via wp_localize_script.
	// Searching/filtering happens on client-side using global commands object

	public static function execute_command( $request ) {
		$command_id   = $request->get_param( 'command_id' );
		$context      = $request->get_param( 'context' ) ?? array();
		$search_query = $request->get_param( 'search_query' ) ?? '';

		// First, check if it's a registered command.
		$command = Registry::get_instance()->get_command( $command_id );

		if ( $command ) {
			return self::execute_registered_command( $command, $request, $context, $search_query );
		}

		// Second, apply filter to let integrations handle dynamic actions.
		$dynamic_result = apply_filters( 'commandify_execute_dynamic_action', null, $command_id, $request );
		if ( null !== $dynamic_result ) {
			if ( is_wp_error( $dynamic_result ) ) {
				return $dynamic_result;
			}
			return rest_ensure_response( $dynamic_result );
		}

		// Finally, check legacy pattern-based dynamic actions.
		if ( self::is_legacy_dynamic_action( $command_id ) ) {
			return self::handle_legacy_dynamic_action( $command_id, $context, $request );
		}

		return new \WP_Error( 'command_not_found', 'Command not found', array( 'status' => 404 ) );
	}

	private static function execute_registered_command( $command, $request, $context, $search_query ) {
		// Apply command filters to ensure callbacks and other enrichments are applied
		// This is important for setting commands that auto-add callbacks
		$command = apply_filters( 'commandify_get_commands', array( $command ) );
		$command = $command[0] ?? $command;
		// Get first command from filtered array

		// Check capability.
		$capability = $command['capability'];
		if ( is_array( $capability ) ) {
			$has_cap = false;
			foreach ( $capability as $cap ) {
				if ( current_user_can( $cap ) ) {
					$has_cap = true;
					break;
				}
			}
			if ( ! $has_cap ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission to execute this command', array( 'status' => 403 ) );
			}
		} elseif ( ! current_user_can( $capability ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission to execute this command', array( 'status' => 403 ) );
		}

		// Handle search command type.
		if ( 'search' === $command['type'] ) {
			if ( ! isset( $command['callback'] ) || ! is_callable( $command['callback'] ) ) {
				return new \WP_Error( 'callback_failed', 'Search callback is not callable', array( 'status' => 500 ) );
			}

			try {
				$results = call_user_func( $command['callback'], $search_query, $context );

				return rest_ensure_response(
					array(
						'success' => true,
						'results' => $results,
						'query'   => $search_query,
					)
				);
			} catch ( \Exception $e ) {
				return new \WP_Error( 'search_failed', $e->getMessage(), array( 'status' => 500 ) );
			}
		}

		// Execute action callback.
		if ( ! isset( $command['callback'] ) || ! is_callable( $command['callback'] ) ) {
			return new \WP_Error( 'callback_failed', 'Command callback is not callable', array( 'status' => 500 ) );
		}

		do_action( 'commandify_before_execute', $command['id'], $context );

		try {
			// Pass the full request object to callback so it can access all params.
			$result = call_user_func( $command['callback'], $request );

			do_action( 'commandify_after_execute', $command['id'], $result, $context );

			// Hook for Pro features to track command execution.
			do_action( 'commandify_command_executed', $command['id'], $command );

			if ( is_array( $result ) ) {
				return rest_ensure_response( $result );
			}

			return rest_ensure_response(
				array(
					'success' => true,
					'message' => 'Command executed successfully',
				)
			);

		} catch ( \Exception $e ) {
			return new \WP_Error( 'callback_failed', $e->getMessage(), array( 'status' => 500 ) );
		}//end try
	}

	public static function verify_nonce( $request ) {
		$nonce = $request->get_header( 'X-WP-Nonce' );

		if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new \WP_Error( 'invalid_nonce', 'Invalid nonce', array( 'status' => 403 ) );
		}

		return current_user_can( 'read' );
	}

	private static function is_legacy_dynamic_action( $command_id ) {
		return strpos( $command_id, 'trash-post-' ) === 0 ||
			strpos( $command_id, 'trash-page-' ) === 0 ||
			strpos( $command_id, 'delete-media-' ) === 0 ||
			strpos( $command_id, 'install-plugin-' ) === 0 ||
			strpos( $command_id, 'activate-plugin-' ) === 0 ||
			strpos( $command_id, 'deactivate-plugin-' ) === 0 ||
			strpos( $command_id, 'install-theme-' ) === 0 ||
			strpos( $command_id, 'activate-theme-' ) === 0;
	}

	private static function handle_legacy_dynamic_action(
		$command_id,
		// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$context = array(),
		// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
		$request = null
	) {
		// Extract post/media ID from command_id (for post/page/media actions)
		preg_match( '/\-(\d+)$/', $command_id, $matches );
		$item_id = ! empty( $matches[1] ) ? intval( $matches[1] ) : null;

		// Extract slug for plugins/themes (everything after the action prefix)
		$slug = null;
		if ( strpos( $command_id, 'install-plugin-' ) === 0 ) {
			$slug = substr( $command_id, strlen( 'install-plugin-' ) );
		} elseif ( strpos( $command_id, 'activate-plugin-' ) === 0 ) {
			$slug = substr( $command_id, strlen( 'activate-plugin-' ) );
		} elseif ( strpos( $command_id, 'deactivate-plugin-' ) === 0 ) {
			$slug = substr( $command_id, strlen( 'deactivate-plugin-' ) );
		} elseif ( strpos( $command_id, 'install-theme-' ) === 0 ) {
			$slug = substr( $command_id, strlen( 'install-theme-' ) );
		} elseif ( strpos( $command_id, 'activate-theme-' ) === 0 ) {
			$slug = substr( $command_id, strlen( 'activate-theme-' ) );
		}

		// Handle trash/delete for any post type (dynamically)
		// Pattern: trash-{post_type}-{id}.
		if ( strpos( $command_id, 'trash-' ) === 0 && $item_id ) {
			// Extract post type from command_id.
			preg_match( '/^trash\-([a-z_\-]+)\-\d+$/', $command_id, $type_matches );
			$post_type = ! empty( $type_matches[1] ) ? $type_matches[1] : 'post';

			// Get the post.
			$post = get_post( $item_id );
			if ( ! $post || $post->post_type !== $post_type ) {
				return new \WP_Error( 'post_not_found', 'Item not found', array( 'status' => 404 ) );
			}

			// Check permissions.
			if ( ! current_user_can( 'delete_post', $item_id ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			// Get post type object for labels.
			$post_type_obj = get_post_type_object( $post_type );
			$label         = $post_type_obj ? strtolower( $post_type_obj->labels->singular_name ) : 'item';

			if ( 'trash' === $post->post_status ) {
				wp_delete_post( $item_id, true );
				return rest_ensure_response(
					array(
						'success' => true,
						/* translators: %s: Post type label */
						'message' => sprintf( __( '%s deleted permanently', 'commandify' ), ucfirst( $label ) ),
					)
				);
			} else {
				wp_trash_post( $item_id );
				return rest_ensure_response(
					array(
						'success' => true,
						/* translators: %s: Post type label */
						'message' => sprintf( __( '%s moved to trash', 'commandify' ), ucfirst( $label ) ),
					)
				);
			}
		}//end if

		// Handle delete media.
		if ( strpos( $command_id, 'delete-media-' ) === 0 ) {
			if ( ! current_user_can( 'delete_post', $item_id ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			wp_delete_attachment( $item_id, true );
			return rest_ensure_response(
				array(
					'success' => true,
					'message' => __( 'Media deleted permanently', 'commandify' ),
				)
			);
		}

		// Handle plugin installation.
		if ( strpos( $command_id, 'install-plugin-' ) === 0 ) {
			if ( ! current_user_can( 'install_plugins' ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			if ( ! $slug ) {
				return new \WP_Error( 'invalid_slug', 'Invalid plugin slug', array( 'status' => 400 ) );
			}

			return self::install_plugin( $slug );
		}

		// Handle plugin activation.
		if ( strpos( $command_id, 'activate-plugin-' ) === 0 ) {
			if ( ! current_user_can( 'activate_plugins' ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			if ( ! $slug ) {
				return new \WP_Error( 'invalid_slug', 'Invalid plugin slug', array( 'status' => 400 ) );
			}

			return self::activate_plugin( $slug );
		}

		// Handle plugin deactivation.
		if ( strpos( $command_id, 'deactivate-plugin-' ) === 0 ) {
			if ( ! current_user_can( 'activate_plugins' ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			if ( ! $slug ) {
				return new \WP_Error( 'invalid_slug', 'Invalid plugin slug', array( 'status' => 400 ) );
			}

			return self::deactivate_plugin( $slug );
		}

		// Handle theme installation.
		if ( strpos( $command_id, 'install-theme-' ) === 0 ) {
			if ( ! current_user_can( 'install_themes' ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			if ( ! $slug ) {
				return new \WP_Error( 'invalid_slug', 'Invalid theme slug', array( 'status' => 400 ) );
			}

			return self::install_theme( $slug );
		}

		// Handle theme activation.
		if ( strpos( $command_id, 'activate-theme-' ) === 0 ) {
			if ( ! current_user_can( 'switch_themes' ) ) {
				return new \WP_Error( 'insufficient_permissions', 'You do not have permission', array( 'status' => 403 ) );
			}

			if ( ! $slug ) {
				return new \WP_Error( 'invalid_slug', 'Invalid theme slug', array( 'status' => 400 ) );
			}

			return self::activate_theme( $slug );
		}

		return new \WP_Error( 'unknown_action', 'Unknown action', array( 'status' => 400 ) );
	}

	private static function install_plugin( $slug ) {
		if ( ! function_exists( 'plugins_api' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
		}
		if ( ! class_exists( 'Plugin_Upgrader' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
		}
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		$api = plugins_api(
			'plugin_information',
			array(
				'slug'   => $slug,
				'fields' => array(
					'sections' => false,
					'tags'     => false,
					'reviews'  => false,
				),
			)
		);

		if ( is_wp_error( $api ) ) {
			return new \WP_Error( 'plugin_not_found', 'Plugin not found on WordPress.org', array( 'status' => 404 ) );
		}

		if ( empty( $api->download_link ) ) {
			return new \WP_Error( 'no_download_link', 'No download link available', array( 'status' => 500 ) );
		}

		$upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin() );
		$result   = $upgrader->install( $api->download_link );

		if ( is_wp_error( $result ) ) {
			return new \WP_Error( 'install_failed', $result->get_error_message(), array( 'status' => 500 ) );
		}

		if ( false === $result ) {
			return new \WP_Error( 'install_failed', 'Installation failed', array( 'status' => 500 ) );
		}

		// Clear cache after successful plugin installation.
		Cache::clear();

		// Return updated actions for the installed plugin.
		$actions = array(
			array(
				'id'                   => 'activate-plugin-' . $slug,
				'title'                => __( 'Activate', 'commandify' ),
				'type'                 => 'action',
				'icon'                 => 'dashicons-yes',
				'has_dynamic_callback' => true,
				/* translators: %s: Plugin name */
				'loading_message'      => sprintf( __( 'Activating %s...', 'commandify' ), $api->name ),
			),
			array(
				'id'       => 'view-plugin-details',
				'title'    => __( 'View in Plugins', 'commandify' ),
				'type'     => 'navigation',
				'callback' => admin_url( 'plugins.php' ),
				'icon'     => 'dashicons-admin-plugins',
			),
		);

		return rest_ensure_response(
			array(
				'success'         => true,
				/* translators: %s: Plugin name */
				'message'         => sprintf( __( 'Plugin "%s" installed successfully!', 'commandify' ), $api->name ),
				'updated_actions' => $actions,
				'plugin_slug'     => $slug,
			)
		);
	}

	private static function activate_plugin( $slug ) {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';

		$plugin_file = self::get_plugin_file_by_slug( $slug );

		if ( ! $plugin_file ) {
			return new \WP_Error( 'plugin_not_found', 'Plugin not installed', array( 'status' => 404 ) );
		}

		$result = activate_plugin( $plugin_file );

		if ( is_wp_error( $result ) ) {
			return new \WP_Error( 'activation_failed', $result->get_error_message(), array( 'status' => 500 ) );
		}

		// Clear cache after successful plugin activation.
		Cache::clear();

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => __( 'Plugin activated successfully!', 'commandify' ),
			)
		);
	}

	private static function deactivate_plugin( $slug ) {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';

		$plugin_file = self::get_plugin_file_by_slug( $slug );

		if ( ! $plugin_file ) {
			return new \WP_Error( 'plugin_not_found', 'Plugin not installed', array( 'status' => 404 ) );
		}

		deactivate_plugins( $plugin_file );

		// Clear cache after successful plugin deactivation.
		Cache::clear();

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => __( 'Plugin deactivated successfully!', 'commandify' ),
			)
		);
	}

	private static function install_theme( $slug ) {
		if ( ! function_exists( 'themes_api' ) ) {
			require_once ABSPATH . 'wp-admin/includes/theme.php';
		}
		if ( ! class_exists( 'Theme_Upgrader' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
		}
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		$api = themes_api(
			'theme_information',
			array(
				'slug'   => $slug,
				'fields' => array(
					'sections' => false,
					'tags'     => false,
					'reviews'  => false,
				),
			)
		);

		if ( is_wp_error( $api ) ) {
			return new \WP_Error( 'theme_not_found', 'Theme not found on WordPress.org', array( 'status' => 404 ) );
		}

		if ( empty( $api->download_link ) ) {
			return new \WP_Error( 'no_download_link', 'No download link available', array( 'status' => 500 ) );
		}

		$upgrader = new \Theme_Upgrader( new \WP_Ajax_Upgrader_Skin() );
		$result   = $upgrader->install( $api->download_link );

		if ( is_wp_error( $result ) ) {
			return new \WP_Error( 'install_failed', $result->get_error_message(), array( 'status' => 500 ) );
		}

		if ( false === $result ) {
			return new \WP_Error( 'install_failed', 'Installation failed', array( 'status' => 500 ) );
		}

		// Clear cache after successful theme installation.
		Cache::clear();

		// Return updated actions for the installed theme.
		$actions = array(
			array(
				'id'                   => 'activate-theme-' . $slug,
				'title'                => __( 'Activate', 'commandify' ),
				'type'                 => 'action',
				'icon'                 => 'dashicons-yes',
				'has_dynamic_callback' => true,
				/* translators: %s: Theme name */
				'loading_message'      => sprintf( __( 'Activating %s...', 'commandify' ), $api->name ),
			),
			array(
				'id'       => 'customize-theme',
				'title'    => __( 'Customize', 'commandify' ),
				'type'     => 'navigation',
				'callback' => admin_url( 'customize.php?theme=' . $slug ),
				'icon'     => 'dashicons-admin-customizer',
			),
			array(
				'id'       => 'view-themes',
				'title'    => __( 'View in Themes', 'commandify' ),
				'type'     => 'navigation',
				'callback' => admin_url( 'themes.php' ),
				'icon'     => 'dashicons-admin-appearance',
			),
		);

		return rest_ensure_response(
			array(
				'success'         => true,
				/* translators: %s: Theme name */
				'message'         => sprintf( __( 'Theme "%s" installed successfully!', 'commandify' ), $api->name ),
				'updated_actions' => $actions,
				'theme_slug'      => $slug,
			)
		);
	}

	private static function activate_theme( $slug ) {
		$theme = wp_get_theme( $slug );

		if ( ! $theme->exists() ) {
			return new \WP_Error( 'theme_not_found', 'Theme not installed', array( 'status' => 404 ) );
		}

		// Check if it's a child theme or parent theme.
		$stylesheet = $theme->get_stylesheet();
		switch_theme( $stylesheet );

		// Clear cache after successful theme activation.
		Cache::clear();

		return rest_ensure_response(
			array(
				'success' => true,
				/* translators: %s: Theme name */
				'message' => sprintf( __( 'Theme "%s" activated successfully!', 'commandify' ), $theme->get( 'Name' ) ),
			)
		);
	}

	private static function get_plugin_file_by_slug( $slug ) {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$plugins = get_plugins();

		foreach ( $plugins as $plugin_file => $plugin_data ) {
			if ( strpos( $plugin_file, $slug . '/' ) === 0 || $plugin_file === $slug . '.php' ) {
				return $plugin_file;
			}
		}

		// Check if slug.php exists directly
		if ( file_exists( WP_PLUGIN_DIR . '/' . $slug . '.php' ) ) {
			return $slug . '.php';
		}

		// Check if slug/slug.php exists
		if ( file_exists( WP_PLUGIN_DIR . '/' . $slug . '/' . $slug . '.php' ) ) {
			return $slug . '/' . $slug . '.php';
		}

		return false;
	}

	public static function get_preferences() {
		$preferences = Settings::get_effective_preferences();

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => $preferences,
			)
		);
	}

	public static function update_preferences( $request ) {
		$preferences = $request->get_param( 'preferences' );

		if ( ! is_array( $preferences ) ) {
			return new \WP_Error( 'invalid_preferences', 'Preferences must be an object', array( 'status' => 400 ) );
		}

		$result = Settings::update_user_preferences( $preferences );

		if ( $result ) {
			return rest_ensure_response(
				array(
					'success' => true,
					'message' => __( 'Preferences updated successfully', 'commandify' ),
					'data'    => Settings::get_effective_preferences(),
				)
			);
		}

		return new \WP_Error( 'update_failed', 'Failed to update preferences', array( 'status' => 500 ) );
	}
}
