<?php
namespace Prodigy\admin;

use Prodigy\Includes\Content\Prodigy_Request_Maker;
use Prodigy\Includes\Content\Prodigy_Settings_Parser;
use Prodigy\Includes\Helpers\Prodigy_Cookies;
use Prodigy\Includes\Helpers\Prodigy_Parameters;
use Prodigy\Includes\Prodigy;
use Prodigy\Includes\Prodigy_Connection;
use Prodigy\Includes\Prodigy_Uninstall_Plugin;
use Prodigy\Includes\Prodigy_User;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Setup Wizard Class
 *
 * Handles the setup wizard functionality for connecting to hosted systems
 * and installing demo content.
 *
 * @version    2.0.0
 * @package    Prodigy
 * @subpackage Prodigy/includes
 */
class Prodigy_Admin_Setup_Wizard {

	const LENGTH_CHARACTERS_TOKEN  = 30;
	const NAME_TOKEN_HOSTED_SYSTEM = 'pg_token_hosted_system';
	const SYNC_CONTENT_FALSE       = 'no';
	const WIZARD_PAGE_SLUG         = 'prodigy-setup';
	const WIZARD_NONCE_ACTION      = 'wizard-form';
	const DEFAULT_STEP             = 1;

	const OPTION_STORE_KEY                   = 'pg_store_key';
	const OPTION_STEP_WIZARD                 = 'pg_step_wizard';
	const OPTION_DOMAIN_HOSTED_SYSTEM        = 'pg_domain_hosted_system';
	const OPTION_URL_DOMAIN_HOSTED_SYSTEM    = 'pg_url_domain_hosted_system';
	const OPTION_INDICATOR_SYNC_CONTENT      = 'pg_indicator_sync_content';
	const OPTION_INSTALL_DEMO_CONTENT_WIZARD = 'pg_install_demo_content_wizard';
	const OPTION_DEMO_CONTENT                = 'prodigy_demo_content';

	const PARAM_TOKEN           = 'token';
	const PARAM_CLEAR           = 'clear';
	const PARAM_REDIRECT_HOSTED = 'redirect_hosted_system';
	const PARAM_STEP            = 'step';
	const PARAM_PAGE            = 'page';
	const PARAM_NONCE           = '_wpnonce';

	/**
	 * Current step
	 *
	 * @var int
	 */
	private int $step = self::DEFAULT_STEP;

	/**
	 * Connected to hosted system
	 *
	 * @var bool
	 */
	private bool $is_connected = false;

	/**
	 * Steps for the setup wizard
	 *
	 * @var array
	 */
	private array $steps = array(
		1 => 'connect_wizard_content',
		2 => 'install_demo_content',
	);

	/**
	 * Page header steps labels
	 *
	 * @var array
	 */
	private array $page_header_steps;

	/**
	 * Page header content labels
	 *
	 * @var array
	 */
	private array $page_header_content;

	/**
	 * URL domain of hosted system
	 *
	 * @var string
	 */
	private string $url_domain_hosted_system;

	/**
	 * Domain of hosted system
	 *
	 * @var string
	 */
	private string $domain_hosted_system;

	/**
	 * Whether products have been created
	 *
	 * @var bool
	 */
	private bool $is_created_products;

	/**
	 * Whether categories have been created
	 *
	 * @var bool
	 */
	private bool $is_created_categories;

	/**
	 * Saved step
	 *
	 * @var int
	 */
	private int $saved_step;

	/**
	 * Product statuses to ignore when counting
	 *
	 * @var array
	 */
	private array $ignore_statuses_product = array( 'auto-draft', 'draft' );

	/** @var Prodigy_User  */
	private Prodigy_User $user;

	/**
	 * Constructor
	 *
	 * Initializes the setup wizard and handles token processing.
	 *
	 * @throws \Exception
	 */
	public function __construct( Prodigy_User $user ) {
		$this->user = $user;
		$this->initialize_properties();
		$this->handle_token_processing();
		$this->handle_clear_data_request();
		$this->handle_redirect_request();
		$this->load_stored_data();
		$this->setup_hooks();
		$this->set_platform_settings();
	}

	/**
	 * @return void
	 */
	public function set_platform_settings() {
		$settings_response = Prodigy_Request_Maker::get_instance()->do_settings_request( 'apps,statistic-apps,external-apps,product-setting,store-customization-settings.customization-error-messages' );
		( new Prodigy_Settings_Parser() )->set_platform_settings( $settings_response );
	}


	/**
	 * Initialize class properties
	 */
	private function initialize_properties(): void {
		$this->page_header_steps = array(
			1 => __( 'Connection', 'prodigy-commerce' ),
			2 => __( 'Demo Content', 'prodigy-commerce' ),
		);

		$this->page_header_content = array(
			1 => __( 'Data Synchronization', 'prodigy-commerce' ),
			2 => __( 'Prodigy Demo Content', 'prodigy-commerce' ),
		);
	}

	/**
	 *
	 * @return bool
	 */
	private function is_wizard_page_request(): bool {
		$page = Prodigy_Parameters::get_parameter( $_GET, self::PARAM_PAGE );

		return is_string( $page ) && $page === self::WIZARD_PAGE_SLUG;
	}

	/**
	 *
	 * @throws \Exception
	 */
	private function handle_token_processing(): void {
		if ( ! $this->is_wizard_page_request() ) {
			return;
		}

		$is_post   = isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST';
		$new_token = $is_post
			? Prodigy_Parameters::get_parameter( $_POST, self::PARAM_TOKEN )
			: Prodigy_Parameters::get_parameter( $_GET, self::PARAM_TOKEN );

		if ( empty( $new_token ) ) {
			return;
		}

		if ( ! $this->verify_nonce( $is_post ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		if ( ! $is_post ) {
			$this->render_token_confirmation_form( $new_token );
			exit;
		}

		$store_connector = new Prodigy_Connection( Prodigy_Request_Maker::get_instance() );

		if ( $store_connector->is_store_already_connected( $new_token ) ) {
			$this->redirect_to_wizard();
			exit;
		}

		if ( $store_connector->has_connected_store() ) {
			$store_connector->disconnect_store();
			$this->clear_content_for_old_store();
			$refresh_key = Prodigy_Cookies::get_cookie( Prodigy_User::REFRESH_COOKIE_NAME );
			$this->user->remove_impersonation_user( $refresh_key );
			$this->user->hosted_system_logout_process( $refresh_key );
			$this->user->logout();
			$this->user->delete_user_cookie();
			$this->user->clear_external_checkout_cookie();
		}

		$store_connector->connect_store( $new_token );
		$this->clear_store_settings();
		$this->redirect_to_wizard();
		exit;
	}

	/**
	 * Output minimal page with form that POSTs token back (user-initiated only).
	 * this is a "confirm connection" intermediary page: GET with a token → display the form → the form is sent via POST → the wizard disconnects (if necessary) and then reconnects via POST. This is how we protect against uncontrolled disconnect calls.
	 *
	 * @param string $token Token from hosted system redirect.
	 */
	private function render_token_confirmation_form( string $token ): void {
		$action = admin_url( 'index.php?page=' . self::WIZARD_PAGE_SLUG );
		$nonce  = wp_create_nonce( self::WIZARD_NONCE_ACTION );
		$title  = __( 'Connecting your store…', 'prodigy-commerce' );
		?>
		<!DOCTYPE html>
		<html>
		<head>
			<meta charset="UTF-8">
			<meta name="viewport" content="width=device-width, initial-scale=1">
			<title><?php echo esc_html( $title ); ?></title>
			<style>
				body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
				.wrap { text-align: center; }
				.spinner { width: 40px; height: 40px; border: 3px solid #ddd; border-top-color: #2271b1; border-radius: 50%; animation: pg-spin 0.8s linear infinite; margin: 0 auto 1rem; }
				@keyframes pg-spin { to { transform: rotate(360deg); } }
			</style>
		</head>
		<body>
			<div class="wrap">
				<div class="spinner" aria-hidden="true"></div>
				<p><?php esc_html_e( 'Connecting your store…', 'prodigy-commerce' ); ?></p>
			</div>
			<form id="pg-token-form" method="post" action="<?php echo esc_url( $action ); ?>">
				<?php wp_nonce_field( self::WIZARD_NONCE_ACTION, self::PARAM_NONCE ); ?>
				<input type="hidden" name="<?php echo esc_attr( self::PARAM_TOKEN ); ?>" value="<?php echo esc_attr( $token ); ?>">
			</form>
			<script>document.getElementById('pg-token-form').submit();</script>
		</body>
		</html>
		<?php
	}

	/**
	 * Redirect to wizard page without token (clean URL).
	 */
	private function redirect_to_wizard(): void {
		$url = admin_url( 'index.php?page=' . self::WIZARD_PAGE_SLUG );
		$url = add_query_arg( '_wpnonce', wp_create_nonce( self::WIZARD_NONCE_ACTION ), $url );
		wp_safe_redirect( $url );
	}

	/**
	 * Handle clear data request
	 */
	private function handle_clear_data_request(): void {
		if ( ! $this->is_wizard_page_request() ) {
			return;
		}

		if ( empty( $_GET[ self::PARAM_CLEAR ] ) ) {
			return;
		}

		$this->clear_data_before_connect();
	}

	/**
	 * Handle redirect to hosted system request
	 */
	private function handle_redirect_request(): void {
		if ( empty( $_GET[ self::PARAM_REDIRECT_HOSTED ] ) ) {
			return;
		}

		if ( ! $this->verify_nonce() ) {
			return;
		}

		$this->redirect_to_hosted_system();
	}

	/**
	 * Load stored data from WordPress options
	 */
	private function load_stored_data(): void {
		$this->is_connected             = get_option( self::OPTION_STORE_KEY );
		$this->saved_step               = get_option( self::OPTION_STEP_WIZARD, self::DEFAULT_STEP );
		$this->domain_hosted_system     = get_option( self::OPTION_DOMAIN_HOSTED_SYSTEM, __( 'Store name domain hosted', 'prodigy-commerce' ) );
		$this->url_domain_hosted_system = get_option( self::OPTION_URL_DOMAIN_HOSTED_SYSTEM, __( 'Store url domain hosted', 'prodigy-commerce' ) );
		$this->is_created_products      = $this->is_created_products();
		$this->is_created_categories    = $this->is_created_categories();
		$this->set_step();
	}

	/**
	 * Setup WordPress hooks
	 */
	private function setup_hooks(): void {
		add_action( 'admin_menu', array( $this, 'admin_menus' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'wizard_enqueue_scripts' ) );
		add_action( 'admin_init', array( $this, 'setup_wizard' ) );
		add_action( 'admin_init', array( $this, 'get_terms_prodigy' ) );
	}

	/**
	 * Verify nonce for security
	 *
	 * @param bool $from_post Whether token came from POST (use POST for nonce); otherwise GET.
	 * @return bool
	 */
	private function verify_nonce( bool $from_post = false ): bool {
		$nonce = $this->get_nonce_from_request( $from_post );
		return ! empty( $nonce ) && wp_verify_nonce( sanitize_key( $nonce ), self::WIZARD_NONCE_ACTION );
	}

	/**
	 * Get nonce from request parameters (GET or POST depending on token source).
	 *
	 * @param bool $from_post Whether to read nonce from POST; otherwise from GET.
	 * @return string|null
	 */
	private function get_nonce_from_request( bool $from_post = false ): ?string {
		$source = $from_post ? $_POST : $_GET;
		if ( ! is_array( $source ) ) {
			return null;
		}
		// Support both _wpnonce and amp;_wpnonce (HTML-escaped query in GET).
		$nonce = Prodigy_Parameters::get_parameter( $source, self::PARAM_NONCE );
		if ( $nonce === null && isset( $source[ self::PARAM_TOKEN ] ) ) {
			$nonce = Prodigy_Parameters::get_parameter( $source, 'amp;_wpnonce' );
		}
		return $nonce;
	}

	/**
	 * Clear content for old store
	 */
	public function clear_content_for_old_store(): void {
		Prodigy_Uninstall_Plugin::delete_products();
		Prodigy_Uninstall_Plugin::delete_categories();
		Prodigy_Uninstall_Plugin::delete_attributes_terms();
	}

	/**
	 * Reset demo settings for new store
	 */
	public function clear_store_settings(): void {
		delete_option( self::OPTION_DEMO_CONTENT );
	}

	/**
	 * Add admin menus/screens
	 */
	public function admin_menus(): void {
		add_dashboard_page( '', '', 'manage_options', self::WIZARD_PAGE_SLUG, '' );
	}

	/**
	 * Check if categories exist
	 *
	 * @return bool
	 */
	public function is_created_categories(): bool {
		$count_cats = wp_count_terms( Prodigy::get_prodigy_category_type() );

		// Ignore default category
		if ( $count_cats === '1' ) {
			$count_cats = 0;
		}

		return (bool) $count_cats;
	}

	/**
	 * Check if products exist
	 *
	 * @return bool
	 */
	public function is_created_products(): bool {
		$count_posts = wp_count_posts( Prodigy::get_prodigy_product_type() );

		if ( ! $count_posts ) {
			return false;
		}

		foreach ( $count_posts as $status => $count ) {
			if ( in_array( $status, $this->ignore_statuses_product, true ) ) {
				continue;
			}

			if ( $count > 0 ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Clear products, categories and attributes and redirect to dashboard
	 *
	 * @return string
	 */
	public function clear_data_before_connect(): string {
		if ( ! $this->is_connected ) {
			$this->clear_pg_content();
		}

		$nonce = wp_create_nonce( self::WIZARD_NONCE_ACTION );
		return admin_url( 'index.php?page=' . self::WIZARD_PAGE_SLUG . '&_wpnonce=' . $nonce );
	}

	/**
	 * Clear products, categories and attributes
	 *
	 * @return string|void
	 */
	public function clear_pg_content() {
		if ( $this->is_connected ) {
			$nonce = wp_create_nonce( self::WIZARD_NONCE_ACTION );
			return admin_url( 'index.php?page=' . self::WIZARD_PAGE_SLUG . '&_wpnonce=' . $nonce );
		}

		$this->clear_content_for_old_store();
	}

	/**
	 * Show the setup wizard
	 */
	public function setup_wizard(): void {
		if ( ! $this->verify_nonce() ) {
			return;
		}

		if ( empty( $_GET[ self::PARAM_PAGE ] ) || self::WIZARD_PAGE_SLUG !== $_GET[ self::PARAM_PAGE ] ) {
			return;
		}

		$step_template = $this->get_template_content_wizard();

		$this->setup_wizard_header();
		$this->$step_template();
		$this->setup_wizard_footer();

		exit;
	}

	/**
	 * Set step for wizard
	 */
	public function set_step(): void {
		if ( ! $this->verify_nonce() ) {
			return;
		}

		$step = Prodigy_Parameters::get_parameter( $_GET, self::PARAM_STEP );

		if ( $step && $this->is_connected && isset( $this->steps[ $step ] ) ) {
			$this->step = (int) $step;
		}
	}

	/**
	 * Get URL for login to hosted system
	 *
	 * @return string
	 */
	public function get_url_login_hosted_system(): string {
		return wp_nonce_url(
			admin_url( 'index.php?page=' . self::WIZARD_PAGE_SLUG . '&' . self::PARAM_REDIRECT_HOSTED . '=1' ),
			self::WIZARD_NONCE_ACTION
		);
	}

	/**
	 * Redirect to hosted system
	 */
	public function redirect_to_hosted_system(): void {
		$sync_content = get_option( self::OPTION_INDICATOR_SYNC_CONTENT );

		if ( $sync_content === self::SYNC_CONTENT_FALSE ) {
			$this->clear_pg_content();
		}

		$this->set_token_for_hosted_system();
		$nonce  = wp_create_nonce( self::WIZARD_NONCE_ACTION );
		$params = array(
			'redirect_url' => wp_nonce_url(
				admin_url( 'index.php?page=' . self::WIZARD_PAGE_SLUG . '&_wpnonce=' . $nonce ),
				self::WIZARD_NONCE_ACTION
			),
		);

		$url = PRODIGY_PROTOCOL_DOMAIN . PRODIGY_MAIN_DOMAIN . '/plugin_connection_stores?' . http_build_query( $params );

		wp_redirect( $url );
		exit;
	}

	/**
	 * Set token for hosted system
	 *
	 * @return bool
	 */
	public function set_token_for_hosted_system(): bool {
		return update_option(
			self::NAME_TOKEN_HOSTED_SYSTEM,
			substr( sha1( wp_rand() ), 0, self::LENGTH_CHARACTERS_TOKEN ),
			false
		);
	}

	/**
	 * Get template content for wizard step
	 *
	 * @return string
	 */
	public function get_template_content_wizard(): string {
		$step = $this->steps[ self::DEFAULT_STEP ];

		if ( $this->is_connected && isset( $this->steps[ $this->step ] ) ) {
			$step = $this->steps[ $this->step ];
		}

		return $step;
	}

	/**
	 * Setup Wizard Header
	 */
	public function setup_wizard_header(): void {
		set_current_screen();
		require_once PRODIGY_PLUGIN_PATH . 'admin/partials/wizard/prodigy-wizard-header-page.php';
	}

	/**
	 * Setup Wizard Footer
	 */
	public function setup_wizard_footer(): void {
		require_once PRODIGY_PLUGIN_PATH . 'admin/partials/wizard/prodigy-wizard-footer-page.php';
	}

	/**
	 * Register/enqueue scripts and styles for the Setup Wizard
	 */
	public function wizard_enqueue_scripts(): void {
		if ( ! did_action( 'wp_enqueue_media' ) ) {
			wp_enqueue_media();
		}

		wp_enqueue_script(
			'wizard',
			Prodigy::plugin_url() . '/assets/admin/wizard/js/wizard.js',
			array( 'jquery' ),
			PRODIGY_VERSION,
			true
		);

		wp_enqueue_style(
			'wizard',
			Prodigy::plugin_url() . '/assets/admin/wizard/css/wizard.css',
			array(),
			PRODIGY_VERSION
		);
	}

	/**
	 * Get Prodigy terms
	 *
	 * @return int[]|string|string[]|\WP_Error|\WP_Term[]
	 */
	public function get_terms_prodigy() {
		return get_terms(
			array(
				'taxonomy'   => Prodigy::get_prodigy_category_type(),
				'hide_empty' => false,
				'parent'     => 0,
			)
		);
	}

	/**
	 * STEP 1: Connect wizard content
	 */
	public function connect_wizard_content(): void {
		update_option( self::OPTION_STEP_WIZARD, 1 );
		require_once PRODIGY_PLUGIN_PATH . 'admin/partials/wizard/prodigy-wizard-step1-page.php';
	}

	/**
	 * STEP 2: Install demo content
	 */
	public function install_demo_content(): void {
		update_option( self::OPTION_STEP_WIZARD, 2 );
		update_option( self::OPTION_INSTALL_DEMO_CONTENT_WIZARD, 0 );

		require_once PRODIGY_PLUGIN_PATH . 'admin/partials/wizard/prodigy-wizard-step2-page.php';
	}
}
