<?php

namespace WC_Affiliate\API;

defined( 'ABSPATH' ) || exit;

use WC_Affiliate\Models\Settings as SettingsModel;
use WC_Affiliate\Traits\Auth;
use WC_Affiliate\Traits\Rest;
use WC_Affiliate\Traits\Validation;
use WP_Error;
use WP_REST_Request;
use WP_REST_Response;

/**
 * Setup Wizard API Controller
 *
 * Handles REST API requests for the multi-step setup wizard process.
 * Manages wizard steps, configuration retrieval, data processing, validation,
 * and progress saving for initial plugin setup.
 *
 * @since   1.0.0
 * @package WC_Affiliate\API
 */
class SetupWizard {

	use Auth;

	use Rest;
	use Validation;

	/**
	 * Get setup wizard defaults.
	 *
	 * @since 1.0.0
	 *
	 * @param WP_REST_Request $request The REST request object containing optional page parameter.
	 *
	 * @return WP_REST_Response The response with setup wizard defaults.
	 */
	public function get_defaults( WP_REST_Request $request ): WP_REST_Response {
		$page = sanitize_text_field( $request->get_param( 'page' ) );

		$settings_model = new SettingsModel();

		if ( $page ) {
			$defaults = $settings_model->get_wizard_page_defaults( $page );
		} else {
			$defaults = $settings_model->get_setup_wizard_defaults();
		}

		return $this->response_success( $defaults );
	}

	/**
	 * Get setup wizard configuration.
	 *
	 * @since 1.0.0
	 *
	 * @param WP_REST_Request $request The REST request object containing optional page parameter.
	 *
	 * @return WP_REST_Response The response with setup wizard configuration.
	 */
	public function get_config( WP_REST_Request $request ): WP_REST_Response {
		$page  = sanitize_text_field( $request->get_param( 'page' ) );
		$pages = wca_get_setup_wizard_pages();

		if ( $page && isset( $pages[ $page ] ) ) {
			return $this->response_success( $pages[ $page ] );
		}

		return $this->response_success( $pages );
	}

	/**
	 * Get setup-wizard values
	 *
	 * @param WP_REST_Request $request REST request object.
	 *
	 * @return WP_Error|WP_REST_Response
	 */
	public function get_values( WP_REST_Request $request ) {
		$page = sanitize_text_field( $request->get_param( 'page' ) );

		// Get setup wizard values using helper function.
		$wizard_data = wca_get_setup_wizard_options( $page );

		return $this->response_success( $wizard_data );
	}

	/**
	 * Update setup-wizard settings
	 *
	 * @param WP_REST_Request $request REST request object.
	 *
	 * @return WP_Error|WP_REST_Response
	 */
	public function update( WP_REST_Request $request ) {
		$page   = sanitize_text_field( $request->get_param( 'page' ) );
		$values = $request->get_param( 'values' );

		// Validate values parameter.
		if ( ! is_array( $values ) ) {
			return $this->response_error( __( 'Invalid data structure', 'wc-affiliate' ), 400 );
		}

		$field_mapping = wca_get_setup_wizard_field_mapping();
		$pages         = wca_get_setup_wizard_pages();

		if ( ! empty( $page ) ) {
			$pages_data[ $page ] = $values;
		} else {
			$pages_data = $values;
		}

		foreach ( $pages_data as $page_key => $page_values ) {
			if ( ! isset( $pages[ $page_key ] ) ) {
				// translators: %s: Settings page key.
				return $this->response_error( sprintf( __( 'Invalid settings page: %s', 'wc-affiliate' ), $page_key ) );
			}

			$validation_result = wca_validate_setup_wizard_values( $page_values, $page_key );
			if ( is_wp_error( $validation_result ) ) {
				return $this->response_error( $validation_result->get_error_message() );
			}
		}

		$result = wca_update_setup_wizard_options( '', $pages_data, $pages, $field_mapping );
		if ( is_wp_error( $result ) ) {
			return $this->response_error( $result->get_error_message() );
		}

		$pages_data = apply_filters( 'wc_affiliate_setup_wizard_updated_values', $pages_data, $page, $pages, $field_mapping );

		return $this->response_success( $pages_data, __( 'Settings updated successfully', 'wc-affiliate' ) );
	}

	/**
	 * Reset setup-wizard progress
	 *
	 * @return WP_REST_Response
	 */
	public function reset_wizard(): WP_REST_Response {
		$option_model  = new SettingsModel();
		$field_mapping = wca_get_setup_wizard_field_mapping();
		$pages         = wca_get_setup_wizard_pages();

		// Reset all wizard pages to defaults using field mapping.
		$reset_values = array();
		foreach ( array_keys( $pages ) as $page_key ) {
			$defaults = $option_model->get_wizard_page_defaults( $page_key );
			if ( ! empty( $defaults ) ) {
				$reset_values[ $page_key ] = $defaults;
			}
		}

		if ( ! empty( $reset_values ) ) {
			wca_update_mapped_wizard_options( $option_model, $field_mapping, $reset_values );
		}

		// Clear wizard data.
		delete_option( SettingsModel::WIZARD_KEY );

		// Clear the setup-wizard completion flag.
		delete_option( 'wc_affiliate_wizard_completed' );

		return $this->response_success( null, __( 'Wizard reset successfully', 'wc-affiliate' ) );
	}

	/**
	 * Complete setup-wizard
	 *
	 * @param WP_REST_Request $request REST request object.
	 *
	 * @return WP_REST_Response
	 */
	public function complete_wizard( WP_REST_Request $request ): WP_REST_Response {
		$values = $request->get_param( 'values' );

		// Validate values parameter.
		if ( is_array( $values ) && ! empty( $values ) ) {
			/**
			 * Fires when the setup wizard is being completed with submitted values.
			 *
			 * This action hook is triggered during the wizard completion process,
			 * allowing other components to react to or process the submitted wizard data
			 * before the wizard is marked as complete.
			 *
			 * @since 3.0.6
			 *
			 * @param array $values The submitted wizard form values from all pages.
			 */
			do_action( 'wc_affiliate_complete_wizard', $values );
		}

		// Mark setup-wizard as completed.
		update_option( 'wc_affiliate_wizard_completed', true );

		// Use settings model to store skip data.
		$settings_model = new SettingsModel();
		$settings_model->set_option( 'wizard', 'skip', array( 'skipped' => false ) );

		// Trigger action for completed wizard.
		do_action( 'wc_affiliate_setup_wizard_completed' );

		$response = array(
			'completed'     => true,
			'redirect_url'  => admin_url( 'admin.php?page=wc-affiliate' ),
			'dashboard_url' => wca_get_dashboard(),
		);

		return $this->response_success( $response, __( 'Setup setup-wizard completed successfully!', 'wc-affiliate' ) );
	}

	/**
	 * Install and/or activate a required platform plugin (e.g. WooCommerce).
	 *
	 * Only WooCommerce is permitted via the allowlist. Installs the plugin from
	 * WordPress.org if it is not present on disk, then activates it.
	 *
	 * @since 1.0.0
	 *
	 * @param WP_REST_Request $request REST request object.
	 *
	 * @return WP_Error|WP_REST_Response
	 */
	public function install_platform( WP_REST_Request $request ) {
		$plugin = sanitize_text_field( $request->get_param( 'plugin' ) );
		$slug   = sanitize_text_field( $request->get_param( 'slug' ) );

		if ( empty( $plugin ) || empty( $slug ) ) {
			return $this->response_error( __( 'Missing plugin or slug parameter.', 'wc-affiliate' ), 400 );
		}

		// Security: allowlist — only supported platform plugins may be managed here.
		$allowed = array(
			'woocommerce/woocommerce.php',
			'easycommerce/easycommerce.php',
		);
		if ( ! in_array( $plugin, $allowed, true ) ) {
			return $this->response_error( __( 'Plugin not allowed.', 'wc-affiliate' ), 403 );
		}

		require_once ABSPATH . 'wp-admin/includes/plugin.php';

		$is_installed = file_exists( WP_PLUGIN_DIR . '/' . $plugin );
		$is_active    = is_plugin_active( $plugin );

		if ( $is_active ) {
			return $this->response_success(
				array( 'status' => 'already_active' ),
				__( 'Plugin is already active.', 'wc-affiliate' )
			);
		}

		// Install from WordPress.org if not on disk yet.
		if ( ! $is_installed ) {
			$install_result = wca_install_plugin( $slug, $plugin );

			if ( is_wp_error( $install_result ) ) {
				return $this->response_error( $install_result->get_error_message(), 500 );
			}
		}

		// Activate (covers both "just installed" and "installed but inactive").
		$activate_result = activate_plugin( $plugin );

		if ( is_wp_error( $activate_result ) ) {
			return $this->response_success(
				array( 'status' => 'installed' ),
				__( 'Plugin installed but could not be activated automatically.', 'wc-affiliate' )
			);
		}

		$status = $is_installed ? 'activated' : 'installed_and_activated';

		return $this->response_success(
			array( 'status' => $status ),
			__( 'Plugin activated successfully.', 'wc-affiliate' )
		);
	}

	/**
	 * Skip setup-wizard
	 *
	 * @param WP_REST_Request $request REST request object.
	 *
	 * @return WP_REST_Response
	 */
	public function skip_wizard( WP_REST_Request $request ): WP_REST_Response {
		$skip_reason        = sanitize_text_field( $request->get_param( 'skip_reason' ) );
		$additional_setting = sanitize_text_field( $request->get_param( 'additional_setting' ) );

		// Use settings model to store skip data.
		$settings_model = new SettingsModel();
		$settings_model->set_option(
			'wizard',
			'skip',
			array(
				'skipped'            => true,
				'skip_reason'        => $skip_reason,
				'additional_setting' => $additional_setting,
			)
		);

		// Trigger action for skipped wizard.
		do_action( 'wc_affiliate_setup_wizard_skipped', $skip_reason, $additional_setting );

		$response = array(
			'skipped'       => true,
			'skip_reason'   => $skip_reason,
			'redirect_url'  => admin_url( 'admin.php?page=wc-affiliate' ),
			'dashboard_url' => wca_get_dashboard(),
			'settings_url'  => admin_url( 'admin.php?page=wc-affiliate#/settings' ),
		);

		return $this->response_success( $response, __( 'Setup wizard skipped successfully!', 'wc-affiliate' ) );
	}
}
