<?php
/**
 * Admin menu, settings page and save handler.
 *
 * @package Ordsync
 */

defined( 'ABSPATH' ) || exit;

/**
 * Everything the store owner sees.
 */
class Ordsync_Admin {

	const PAGE       = 'ordsync';
	const CAPABILITY = 'manage_woocommerce';

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'admin_menu', array( $this, 'menu' ) );
		add_action( 'admin_post_ordsync_save', array( $this, 'save' ) );
		add_action( 'admin_post_ordsync_regenerate_secret', array( $this, 'regenerate_secret' ) );
		add_action( 'admin_post_ordsync_regenerate_webhook_secret', array( $this, 'regenerate_webhook_secret' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'assets' ) );
		add_filter(
			'plugin_action_links_' . plugin_basename( ORDSYNC_FILE ),
			array( $this, 'action_links' )
		);
	}

	/**
	 * Add the submenu under WooCommerce.
	 *
	 * @return void
	 */
	public function menu() {
		add_submenu_page(
			'woocommerce',
			__( 'OrderCarry', 'ordercarry-order-automation-for-woocommerce' ),
			__( 'OrderCarry', 'ordercarry-order-automation-for-woocommerce' ),
			self::CAPABILITY,
			self::PAGE,
			array( $this, 'render' )
		);
	}

	/**
	 * "Settings" link on the Plugins screen.
	 *
	 * @param array $links Existing links.
	 * @return array
	 */
	public function action_links( $links ) {
		$url = admin_url( 'admin.php?page=' . self::PAGE );
		array_unshift(
			$links,
			'<a href="' . esc_url( $url ) . '">' . esc_html__( 'Settings', 'ordercarry-order-automation-for-woocommerce' ) . '</a>'
		);
		return $links;
	}

	/**
	 * Load CSS and JS, only on our page.
	 *
	 * @param string $hook Current admin page hook.
	 * @return void
	 */
	public function assets( $hook ) {
		if ( 'woocommerce_page_' . self::PAGE !== $hook ) {
			return;
		}

		/*
		 * Depends on dashicons so the status icons resolve. WordPress already
		 * loads that font in wp-admin; declaring it means we never rely on
		 * another plugin having enqueued it first.
		 */
		wp_enqueue_style(
			'ordsync-admin',
			ORDSYNC_URL . 'admin/assets/admin.css',
			array( 'dashicons' ),
			self::asset_version( 'admin/assets/admin.css' )
		);

		wp_enqueue_script(
			'ordsync-admin',
			ORDSYNC_URL . 'admin/assets/admin.js',
			array( 'jquery' ),
			self::asset_version( 'admin/assets/admin.js' ),
			true
		);

		wp_localize_script(
			'ordsync-admin',
			'ordsyncData',
			array(
				'ajaxUrl'  => admin_url( 'admin-ajax.php' ),
				'nonce'    => wp_create_nonce( 'ordsync_test' ),
				'testing'  => __( 'Sending test order…', 'ordercarry-order-automation-for-woocommerce' ),
				'copied'   => __( 'Copied!', 'ordercarry-order-automation-for-woocommerce' ),
				'copyFail' => __( 'Could not copy — select the text and copy it manually.', 'ordercarry-order-automation-for-woocommerce' ),
				'confirmDelete' => __( 'Delete this destination and its rules?', 'ordercarry-order-automation-for-woocommerce' ),
				'importing'     => __( 'Queueing orders…', 'ordercarry-order-automation-for-woocommerce' ),
				'retrying'      => __( 'Queueing…', 'ordercarry-order-automation-for-woocommerce' ),
				'switchOn'      => __( 'On', 'ordercarry-order-automation-for-woocommerce' ),
				'switchOff'     => __( 'Off', 'ordercarry-order-automation-for-woocommerce' ),
				'confirmImport' => __( 'Send your past orders to this destination? Orders already sent here are skipped.', 'ordercarry-order-automation-for-woocommerce' ),
			)
		);
	}

	/**
	 * Cache-busting version string for an asset.
	 *
	 * The plugin version alone is not enough: any release that changes CSS or
	 * JS without bumping the version leaves every existing admin on a stale
	 * cached copy, and the new interface silently does nothing. Appending the
	 * file's modification time makes the URL change whenever the file does.
	 *
	 * @param string $relative Path relative to the plugin root.
	 * @return string
	 */
	private static function asset_version( $relative ) {
		$path = ORDSYNC_PATH . $relative;

		if ( file_exists( $path ) ) {
			return ORDSYNC_VERSION . '.' . filemtime( $path );
		}

		return ORDSYNC_VERSION;
	}

	/**
	 * Render the settings page.
	 *
	 * @return void
	 */
	public function render() {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to view this page.', 'ordercarry-order-automation-for-woocommerce' ) );
		}

		$settings       = Ordsync_Settings::all();
		$secret         = Ordsync_Settings::secret();
		$webhook_secret = Ordsync_Settings::webhook_secret();
		$statuses       = Ordsync_Settings::order_statuses();
		$tab      = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'sheets'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		require ORDSYNC_PATH . 'admin/views/page-settings.php';
	}

	/**
	 * Save the settings.
	 *
	 * @return void
	 */
	public function save() {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'ordercarry-order-automation-for-woocommerce' ) );
		}

		check_admin_referer( 'ordsync_save' );

		$tab = isset( $_POST['tab'] ) ? sanitize_key( wp_unslash( $_POST['tab'] ) ) : 'sheets';

		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized field by field in Ordsync_Settings::sanitize_group().
		$raw = isset( $_POST['ordsync'][ $tab ] ) ? wp_unslash( $_POST['ordsync'][ $tab ] ) : array();

		if ( ! is_array( $raw ) ) {
			$raw = array();
		}

		$clean = Ordsync_Settings::sanitize_type( $tab, $raw );

		if ( $clean ) {
			// Only the edited tab changes. The others keep whatever they had.
			$settings         = Ordsync_Settings::all();
			$settings[ $tab ] = $clean;
			Ordsync_Settings::save( $settings );
			Ordsync_Destinations::flush();
		}

		wp_safe_redirect(
			add_query_arg(
				array(
					'page'    => self::PAGE,
					'tab'     => $tab,
					'updated' => '1',
				),
				admin_url( 'admin.php' )
			)
		);
		exit;
	}

	/**
	 * Make a new secret.
	 *
	 * @return void
	 */
	public function regenerate_secret() {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'ordercarry-order-automation-for-woocommerce' ) );
		}

		check_admin_referer( 'ordsync_regenerate_secret' );

		Ordsync_Settings::regenerate_secret();

		wp_safe_redirect(
			add_query_arg(
				array(
					'page'         => self::PAGE,
					'tab'          => 'sheets',
					'secret_reset' => '1',
				),
				admin_url( 'admin.php' )
			)
		);
		exit;
	}

	/**
	 * Make a new webhook signing key.
	 *
	 * Separate from regenerate_secret() on purpose: rotating one must never
	 * silently invalidate the other.
	 *
	 * @return void
	 */
	public function regenerate_webhook_secret() {
		if ( ! current_user_can( self::CAPABILITY ) ) {
			wp_die( esc_html__( 'You do not have permission to do this.', 'ordercarry-order-automation-for-woocommerce' ) );
		}

		check_admin_referer( 'ordsync_regenerate_webhook_secret' );

		Ordsync_Settings::regenerate_webhook_secret();

		wp_safe_redirect(
			add_query_arg(
				array(
					'page'                 => self::PAGE,
					'tab'                  => 'webhook',
					'webhook_secret_reset' => '1',
				),
				admin_url( 'admin.php' )
			)
		);
		exit;
	}
}
