<?php
/**
 * Shared Square connection settings (WooCommerce + Contact Form 7).
 *
 * @package SHC4WC
 */

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

class SHC4WC_Connection_Settings {
	private static $instance = null;

	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_action( 'admin_menu', array( $this, 'register_menu' ) );
		add_action( 'admin_init', array( $this, 'register_settings' ) );
		add_action( 'admin_notices', array( $this, 'admin_notice' ) );
	}

	public static function page_slug() {
		return 'payments-square-connect';
	}

	public static function page_url( $status = '' ) {
		$args = array();
		if ( $status ) {
			$args['shc4wc_status'] = $status;
		}
		return SHC4WC_Admin_Menu::page_url( SHC4WC_Admin_Menu::CONNECT_SLUG, $args );
	}

	/**
	 * Sandbox setup hint shown before connecting in Sandbox mode.
	 *
	 * @return string
	 */
	public static function get_sandbox_connect_hint_html() {
		$sandbox_console_url = 'https://developer.squareup.com/console/en/sandbox-test-accounts';

		$html  = '<p class="description shc4wc-sandbox-connect-hint" style="margin-top:8px;">';
		$html .= wp_kses(
			sprintf(
				/* translators: %s: link to Square Sandbox test accounts in the Developer Console */
				__( 'Sandbox setup: open the <a href="%s" target="_blank" rel="noopener noreferrer">Square Sandbox dashboard</a>, sign in to your test seller account, then return here and click <strong>Connect Square for Sandbox</strong>.', 'payments-connect-square' ),
				esc_url( $sandbox_console_url )
			),
			array(
				'a'      => array(
					'href'   => array(),
					'target' => array(),
					'rel'    => array(),
				),
				'strong' => array(),
			)
		);
		$html .= '</p>';

		return $html;
	}

	public function register_menu() {
		SHC4WC_Admin_Menu::register_parent_menu();

		add_submenu_page(
			SHC4WC_Admin_Menu::MENU_SLUG,
			__( 'Payments Square Connect', 'payments-connect-square' ),
			__( 'Payments Square Connect', 'payments-connect-square' ),
			'manage_options',
			SHC4WC_Admin_Menu::CONNECT_SLUG,
			array( $this, 'render_page' )
		);
	}

	public function register_settings() {
		register_setting(
			'shc4wc_connection',
			'woocommerce_shc4wc_settings',
			array(
				'type'              => 'array',
				'sanitize_callback' => array( $this, 'sanitize_settings' ),
			)
		);
	}

	public function sanitize_settings( $input ) {
		$current = SHC4WC_Plugin::get_raw_settings();
		$merged  = is_array( $current ) ? $current : array();
		if ( ! is_array( $input ) ) {
			return SHC4WC_Plugin::normalize_settings( $merged );
		}

		/*
		 * Dedicated option for WP-Cron customer sync (read via get_option).
		 * Unchecked checkboxes are omitted from POST — treat missing as off.
		 */
		$sync_enabled = ( ! empty( $input['square_enable_marketing_sync'] ) && 'yes' === $input['square_enable_marketing_sync'] )
			? 'yes'
			: 'no';
		update_option( 'square_enable_marketing_sync', $sync_enabled, false );
		unset( $input['square_enable_marketing_sync'] );

		$direction = isset( $input['square_customer_sync_direction'] )
			? sanitize_text_field( (string) $input['square_customer_sync_direction'] )
			: 'square_to_wp';
		$allowed_directions = array( 'square_to_wp', 'wp_to_square', 'both' );
		if ( ! in_array( $direction, $allowed_directions, true ) ) {
			$direction = 'square_to_wp';
		}
		update_option( 'square_customer_sync_direction', $direction, false );
		unset( $input['square_customer_sync_direction'] );

		$include_existing = ( ! empty( $input['square_customer_sync_include_existing'] ) && 'yes' === $input['square_customer_sync_include_existing'] )
			? 'yes'
			: 'no';
		update_option( 'square_customer_sync_include_existing', $include_existing, false );
		unset( $input['square_customer_sync_include_existing'] );

		$old_env = ( isset( $current['environment'] ) && 'live' === $current['environment'] ) ? 'live' : 'sandbox';

		$keys = array(
			'environment',
			'location_id',
			'debug',
			'ai_openai_api_key',
		);
		foreach ( $keys as $key ) {
			if ( array_key_exists( $key, $input ) ) {
				if ( 'ai_openai_api_key' === $key ) {
					$value = trim( (string) $input[ $key ] );
					if ( '' !== $value ) {
						$merged[ $key ] = sanitize_text_field( $value );
					}
					continue;
				}
				$merged[ $key ] = $input[ $key ];
			}
		}

		if ( ! isset( $merged['location_ids'] ) || ! is_array( $merged['location_ids'] ) ) {
			$merged['location_ids'] = array();
		}

		if ( array_key_exists( 'environment', $input ) ) {
			$new_env = ( isset( $merged['environment'] ) && 'live' === $merged['environment'] ) ? 'live' : 'sandbox';
			if ( $old_env !== $new_env ) {
				$normalized_current = SHC4WC_Plugin::normalize_settings( $current );
				if ( ! empty( $normalized_current['location_ids'][ $old_env ] ) ) {
					$merged['location_ids'][ $old_env ] = sanitize_text_field( (string) $normalized_current['location_ids'][ $old_env ] );
				} elseif ( ! empty( $current['location_id'] ) ) {
					$merged['location_ids'][ $old_env ] = sanitize_text_field( (string) $current['location_id'] );
				}
				$merged['location_id'] = ! empty( $merged['location_ids'][ $new_env ] )
					? sanitize_text_field( (string) $merged['location_ids'][ $new_env ] )
					: '';

				if ( SHC4WC_Plugin::has_oauth_for_environment( $new_env ) ) {
					set_transient( 'shc4wc_environment_changed_notice', 'ready_' . $new_env, MINUTE_IN_SECONDS );
				} else {
					set_transient( 'shc4wc_environment_changed_notice', 'missing_' . $new_env, MINUTE_IN_SECONDS );
				}
			}
		}

		$active_env = ( isset( $merged['environment'] ) && 'live' === $merged['environment'] ) ? 'live' : 'sandbox';
		if ( array_key_exists( 'location_id', $input ) && '' !== trim( (string) $merged['location_id'] ) ) {
			$merged['location_ids'][ $active_env ] = sanitize_text_field( (string) $merged['location_id'] );
		}

		return SHC4WC_Plugin::normalize_settings( $merged );
	}

	public function admin_notice() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$page = (string) filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
		if ( self::page_slug() !== $page ) {
			return;
		}

		$env_changed = get_transient( 'shc4wc_environment_changed_notice' );
		if ( is_string( $env_changed ) && '' !== $env_changed ) {
			delete_transient( 'shc4wc_environment_changed_notice' );
			$notice_type = 'info';
			$message     = '';

			if ( 0 === strpos( $env_changed, 'ready_' ) ) {
				$env_key = substr( $env_changed, 6 );
				$label   = 'sandbox' === $env_key ? __( 'Sandbox', 'payments-connect-square' ) : __( 'Live', 'payments-connect-square' );
				$message = sprintf(
					/* translators: %s: Sandbox or Live */
					__( 'Switched to %s. Your saved Square connection for this mode is now active.', 'payments-connect-square' ),
					$label
				);
			} elseif ( 0 === strpos( $env_changed, 'missing_' ) ) {
				$env_key     = substr( $env_changed, 8 );
				$label       = 'sandbox' === $env_key ? __( 'Sandbox', 'payments-connect-square' ) : __( 'Live', 'payments-connect-square' );
				$notice_type = 'warning';
				$message     = sprintf(
					/* translators: %1$s: Sandbox or Live (shown twice) */
					__( '%1$s is not connected yet. Choose %1$s above, click Connect with Square once, then pick a location. After that, switching between Live and Sandbox will be automatic.', 'payments-connect-square' ),
					$label
				);
			}

			if ( '' !== $message ) {
				printf(
					'<div class="notice notice-%1$s is-dismissible"><p>%2$s</p></div>',
					esc_attr( $notice_type ),
					esc_html( $message )
				);
			}
		}

		static $shown_statuses = array();

		$status = (string) filter_input( INPUT_GET, 'shc4wc_status', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
		if ( '' === $status || isset( $shown_statuses[ $status ] ) ) {
			return;
		}

		$map = array(
			'connected'                       => array( 'success', __( 'Square connected successfully.', 'payments-connect-square' ) ),
			'disconnected'                    => array( 'success', __( 'Square disconnected.', 'payments-connect-square' ) ),
			'missing_client_id'               => array( 'error', __( 'Client ID not found in credentials JSON for selected environment.', 'payments-connect-square' ) ),
			'oauth_denied'                    => array( 'error', __( 'Square authorization denied by user.', 'payments-connect-square' ) ),
			'oauth_state_error'               => array( 'error', __( 'OAuth state validation failed.', 'payments-connect-square' ) ),
			'oauth_request_failed'            => array( 'error', __( 'Could not connect to Square token endpoint.', 'payments-connect-square' ) ),
			'oauth_exchange_failed'           => array( 'error', __( 'Square token exchange failed.', 'payments-connect-square' ) ),
			'oauth_locations_failed'          => array( 'error', __( 'Access token received, but locations could not be fetched. Check permissions and retry.', 'payments-connect-square' ) ),
			'oauth_worker_misconfigured'      => array( 'error', __( 'Square login could not start. This site could not register with the OAuth service or the connection key was not saved. Enable Debug Log below and try again to see technical details.', 'payments-connect-square' ) ),
			'worker_register_invalid_base'    => array( 'error', __( 'Worker base URL must start with https://.', 'payments-connect-square' ) ),
			'worker_register_failed'          => array( 'error', __( 'Could not register this site with the OAuth service. Enable Debug Log below and try again to see technical details.', 'payments-connect-square' ) ),
			'worker_register_secret_required' => array(
				'error',
				__(
					'The OAuth Worker requires a registration secret. Set oauth_worker_registration_secret in shc4wc-host-config.php to the same value as Cloudflare secret REGISTRATION_SECRET - or remove REGISTRATION_SECRET from the Worker for open registration.',
					'payments-connect-square'
				),
			),
			'worker_register_unreachable'     => array(
				'error',
				__( 'Could not reach the OAuth Worker (network error). Check the Worker URL, firewall, and PHP SSL.', 'payments-connect-square' ),
			),
			'worker_register_bad_home_url'    => array(
				'error',
				__( 'The Worker rejected your site URL. In Settings -> General, set WordPress Address and Site Address to a full URL starting with http:// or https://.', 'payments-connect-square' ),
			),
			'worker_registered'               => array( 'success', __( 'Store registered. You can connect Payments Square Connect.', 'payments-connect-square' ) ),
			'oauth_claim_failed'              => array( 'error', __( 'Could not complete OAuth with the Worker (claim failed or session expired). Try connecting again.', 'payments-connect-square' ) ),
		);

		if ( ! isset( $map[ $status ] ) ) {
			return;
		}

		$shown_statuses[ $status ] = true;
		list( $type, $message )    = $map[ $status ];
		printf( '<div class="notice notice-%1$s"><p>%2$s</p>', esc_attr( $type ), esc_html( $message ) );
		self::render_admin_diagnostics_notice();
		echo '</div>';
	}

	/**
	 * Show last Worker/connect failure details when Debug Log is enabled.
	 */
	public static function render_admin_diagnostics_notice() {
		$settings = SHC4WC_Plugin::get_settings();
		if ( empty( $settings['debug'] ) || 'yes' !== $settings['debug'] ) {
			return;
		}

		$diag = SHC4WC_Plugin::get_admin_diagnostics();
		if ( empty( $diag ) ) {
			return;
		}

		$lines = array();
		if ( ! empty( $diag['context'] ) ) {
			$lines[] = sprintf(
				/* translators: %s: internal context label. */
				__( 'Step: %s', 'payments-connect-square' ),
				(string) $diag['context']
			);
		}
		if ( ! empty( $diag['worker_error'] ) ) {
			$lines[] = sprintf(
				/* translators: %s: worker error code. */
				__( 'Worker error: %s', 'payments-connect-square' ),
				(string) $diag['worker_error']
			);
		}
		if ( ! empty( $diag['transport_error'] ) ) {
			$lines[] = sprintf(
				/* translators: %s: PHP HTTP transport error. */
				__( 'Network error: %s', 'payments-connect-square' ),
				(string) $diag['transport_error']
			);
		}
		if ( ! empty( $diag['http_code'] ) ) {
			$lines[] = sprintf(
				/* translators: %d: HTTP status code. */
				__( 'HTTP status: %d', 'payments-connect-square' ),
				(int) $diag['http_code']
			);
		}
		if ( ! empty( $diag['raw_snippet'] ) ) {
			$lines[] = sprintf(
				/* translators: %s: short response body. */
				__( 'Response: %s', 'payments-connect-square' ),
				(string) $diag['raw_snippet']
			);
		}
		if ( isset( $diag['site_key_set'] ) ) {
			$lines[] = $diag['site_key_set']
				? __( 'Connection key: saved', 'payments-connect-square' )
				: __( 'Connection key: missing', 'payments-connect-square' );
		}
		if ( ! empty( $diag['worker_base'] ) ) {
			$lines[] = sprintf(
				/* translators: %s: worker URL. */
				__( 'Worker: %s', 'payments-connect-square' ),
				(string) $diag['worker_base']
			);
		}
		if ( ! empty( $diag['site_url'] ) ) {
			$lines[] = sprintf(
				/* translators: %s: WordPress site URL. */
				__( 'Site URL sent: %s', 'payments-connect-square' ),
				(string) $diag['site_url']
			);
		}

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

		echo '<p><strong>' . esc_html__( 'Technical details', 'payments-connect-square' ) . '</strong></p><ul style="list-style:disc;margin-left:1.5em;">';
		foreach ( $lines as $line ) {
			echo '<li>' . esc_html( $line ) . '</li>';
		}
		echo '</ul>';
	}

	public function render_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$settings = SHC4WC_Plugin::get_settings();
		$settings['square_enable_marketing_sync'] = get_option( 'square_enable_marketing_sync', 'no' );
		$settings['square_customer_sync_direction'] = class_exists( 'SHC4WC_Customer_Sync' )
			? SHC4WC_Customer_Sync::get_direction()
			: get_option( 'square_customer_sync_direction', 'square_to_wp' );
		$settings['square_customer_sync_include_existing'] = class_exists( 'SHC4WC_Customer_Sync' )
			? ( SHC4WC_Customer_Sync::include_existing_on_manual() ? 'yes' : 'no' )
			: get_option( 'square_customer_sync_include_existing', 'no' );
		$fields   = $this->get_connection_fields();
		?>
		<div class="wrap">
			<h1><?php esc_html_e( 'Payments Square Connect', 'payments-connect-square' ); ?></h1>
			<p><?php esc_html_e( 'Set up Payments Square Connect once here. WooCommerce checkout and Contact Form 7 both use this connection when those plugins are active.', 'payments-connect-square' ); ?></p>
			<form method="post" action="options.php">
				<?php settings_fields( 'shc4wc_connection' ); ?>
				<table class="form-table" role="presentation">
					<?php
					foreach ( $fields as $key => $field ) {
						$this->render_field_row( $key, $field, $settings );
					}
					?>
				</table>
				<?php submit_button( __( 'Save connection settings', 'payments-connect-square' ) ); ?>
			</form>
			<?php if ( class_exists( 'WooCommerce' ) ) : ?>
				<p>
					<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=checkout&section=shc4wc' ) ); ?>">
						<?php esc_html_e( 'WooCommerce checkout display settings', 'payments-connect-square' ); ?>
					</a>
				</p>
			<?php endif; ?>
			<p>
				<a href="<?php echo esc_url( SHC4WC_Admin_Menu::page_url( SHC4WC_Onboarding::PAGE_SLUG ) ); ?>">
					<?php esc_html_e( 'Setup guide (onboarding)', 'payments-connect-square' ); ?>
				</a>
				|
				<a href="<?php echo esc_url( SHC4WC_Admin_Menu::page_url( SHC4WC_Admin_Menu::CHECKOUT_SLUG ) ); ?>">
					<?php esc_html_e( 'Checkout Settings (Square hosted checkout)', 'payments-connect-square' ); ?>
				</a>
				|
				<a href="<?php echo esc_url( SHC4WC_Admin_Menu::page_url( SHC4WC_Admin_Menu::SUBSCRIPTIONS_SLUG ) ); ?>">
					<?php esc_html_e( 'Subscription Plans', 'payments-connect-square' ); ?>
				</a>
				|
				<a href="<?php echo esc_url( SHC4WC_Admin_Menu::page_url( SHC4WC_Admin_Menu::SUPPORT_SLUG ) ); ?>">
					<?php esc_html_e( 'Support', 'payments-connect-square' ); ?>
				</a>
			</p>
		</div>
		<?php
	}

	private function get_connection_fields() {
		$location_options = $this->get_location_options();
		$has_oauth        = SHC4WC_Plugin::has_oauth_connection();

		$fields = array(
			'environment' => array(
				'title'   => __( 'Environment', 'payments-connect-square' ),
				'type'    => 'select',
				'options' => array(
					'sandbox' => __( 'Sandbox', 'payments-connect-square' ),
					'live'    => __( 'Live', 'payments-connect-square' ),
				),
			),
			'shc4wc_square_connect_title' => array(
				'title'       => __( 'Square account', 'payments-connect-square' ),
				'type'        => 'title',
				'description' => __( 'Choose Sandbox or Live above, then connect your Square account. Setup runs automatically in the background.', 'payments-connect-square' ),
			),
			'oauth_actions'               => array(
				'title' => __( 'Payments Square Connect', 'payments-connect-square' ),
				'type'  => 'shc4wc_oauth_actions',
			),
		);

		if ( $has_oauth ) {
			$fields['location_id'] = array(
				'title'       => __( 'Square Location', 'payments-connect-square' ),
				'type'        => 'select',
				'options'     => $location_options,
				'description' => $this->get_location_usage_description(),
			);
		}

		$fields['square_enable_marketing_sync'] = array(
			'title'       => __( 'Customer sync', 'payments-connect-square' ),
			'type'        => 'checkbox',
			'label'       => __( 'Enable automatic customer sync every 15 minutes', 'payments-connect-square' ),
			'description' => __( 'Runs every 15 minutes via WP-Cron. Each run looks back 1 hour so delayed jobs do not miss customers (overlap). Matches by Square customer ID then email. No Square webhooks required. Enable Debug Log to review activity.', 'payments-connect-square' ),
		);
		$fields['square_customer_sync_direction'] = array(
			'title'       => __( 'Sync direction', 'payments-connect-square' ),
			'type'        => 'select',
			'options'     => array(
				'square_to_wp' => __( 'Square → WordPress', 'payments-connect-square' ),
				'wp_to_square' => __( 'WordPress → Square', 'payments-connect-square' ),
				'both'         => __( 'Both ways', 'payments-connect-square' ),
			),
			'description' => __( 'Square → WordPress: create/update WordPress users (customer role when available). WordPress → Square: push recent WordPress customers into Square. Both ways runs each direction in one sync.', 'payments-connect-square' ),
		);
		$fields['square_customer_sync_include_existing'] = array(
			'title'       => __( 'Include existing', 'payments-connect-square' ),
			'type'        => 'checkbox',
			'label'       => __( 'When Sync customers runs, also sync all existing customers in the background', 'payments-connect-square' ),
			'description' => __( 'Saved with connection settings. Existing customers sync in small background batches (~25 every 30s) so the site stays light. Automatic cron still only syncs recent customers (last 1 hour).', 'payments-connect-square' ),
		);
		$fields['customer_sync_now'] = array(
			'title' => '',
			'type'  => 'shc4wc_customer_sync_now',
		);
		$fields['square_inventory_sync_from_square'] = array(
			'title'            => __( 'Inventory sync (Square → WooCommerce)', 'payments-connect-square' ),
			'type'             => 'checkbox',
			'label'            => __( 'Update WooCommerce stock when Square inventory changes (webhook)', 'payments-connect-square' ),
			'description_html' => $this->get_inventory_sync_description_html(),
		);
		$fields['debug'] = array(
			'title' => __( 'Debug Log', 'payments-connect-square' ),
			'type'  => 'checkbox',
			'label' => __( 'Enable logging', 'payments-connect-square' ),
		);
		$fields['ai_openai_api_key'] = array(
			'title'       => __( 'OpenAI API key (optional)', 'payments-connect-square' ),
			'type'        => 'password',
			'description' => __( 'Powers the optional AI setup assistant on Get started. Your key is stored on this site and sent only to OpenAI when you click Get AI help. Leave blank to keep the current key.', 'payments-connect-square' ),
		);
		$fields['webhook_url'] = array(
			'title' => __( 'Webhook URL', 'payments-connect-square' ),
			'type'  => 'shc4wc_webhook_url',
		);

		return $fields;
	}

	private function get_location_usage_description() {
		$parts = array();
		if ( class_exists( 'WooCommerce' ) ) {
			$parts[] = __( 'WooCommerce checkout', 'payments-connect-square' );
		}
		if ( defined( 'WPCF7_VERSION' ) || class_exists( 'WPCF7' ) ) {
			$parts[] = __( 'Contact Form 7 payments', 'payments-connect-square' );
		}
		if ( empty( $parts ) ) {
			return __( 'Used for Square payments on this site.', 'payments-connect-square' );
		}
		return sprintf(
			/* translators: %s: comma-separated list of integrations. */
			__( 'Used for %s.', 'payments-connect-square' ),
			implode( ', ', $parts )
		);
	}

	private function get_location_options() {
		$locations = SHC4WC_Plugin::get_locations();
		if ( empty( $locations ) ) {
			return array(
				'' => __( 'Use Payments Square Connect to load locations', 'payments-connect-square' ),
			);
		}
		$options = array( '' => __( 'Select a location', 'payments-connect-square' ) );
		foreach ( $locations as $location ) {
			if ( empty( $location['id'] ) ) {
				continue;
			}
			$name                       = ! empty( $location['name'] ) ? $location['name'] : $location['id'];
			$options[ $location['id'] ] = sprintf( '%s (%s)', $name, $location['id'] );
		}
		return $options;
	}

	private function render_field_row( $key, $field, $settings ) {
		$type  = isset( $field['type'] ) ? $field['type'] : 'text';
		$title = isset( $field['title'] ) ? $field['title'] : $key;
		$value = isset( $settings[ $key ] ) ? $settings[ $key ] : '';

		if ( 'title' === $type ) {
			echo '<tr><td colspan="2"><h2 class="title">' . esc_html( $title ) . '</h2>';
			if ( ! empty( $field['description'] ) ) {
				echo '<p class="description">' . esc_html( $field['description'] ) . '</p>';
			}
			echo '</td></tr>';
			return;
		}

		if ( in_array( $type, array( 'shc4wc_oauth_actions', 'shc4wc_worker_register', 'shc4wc_webhook_url', 'shc4wc_customer_sync_now' ), true ) ) {
			if ( 'shc4wc_oauth_actions' === $type ) {
				// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
				echo self::render_oauth_actions_row( $title );
				return;
			}
			if ( 'shc4wc_webhook_url' === $type ) {
				// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
				echo self::render_webhook_url_row( $title );
				return;
			}
			if ( 'shc4wc_customer_sync_now' === $type ) {
				// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
				echo self::render_customer_sync_now_row();
				return;
			}
			if ( 'shc4wc_worker_register' === $type && class_exists( 'SHC4WC_Gateway' ) ) {
				$gateway = new SHC4WC_Gateway();
				if ( method_exists( $gateway, 'generate_shc4wc_worker_register_html' ) ) {
					// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					echo $gateway->generate_shc4wc_worker_register_html( $key, $field );
					return;
				}
			}
		}

		echo '<tr><th scope="row"><label for="shc4wc_' . esc_attr( $key ) . '">' . esc_html( $title ) . '</label></th><td>';

		if ( 'select' === $type ) {
			$input_name = ( 'square_customer_sync_direction' === $key )
				? 'woocommerce_shc4wc_settings[square_customer_sync_direction]'
				: 'woocommerce_shc4wc_settings[' . $key . ']';
			$select_value = ( 'square_customer_sync_direction' === $key )
				? ( class_exists( 'SHC4WC_Customer_Sync' ) ? SHC4WC_Customer_Sync::get_direction() : (string) $value )
				: (string) $value;
			echo '<select name="' . esc_attr( $input_name ) . '" id="shc4wc_' . esc_attr( $key ) . '">';
			foreach ( (array) $field['options'] as $opt_key => $label ) {
				printf(
					'<option value="%1$s" %2$s>%3$s</option>',
					esc_attr( $opt_key ),
					selected( $select_value, (string) $opt_key, false ),
					esc_html( $label )
				);
			}
			echo '</select>';
		} elseif ( 'checkbox' === $type ) {
			$input_name = 'woocommerce_shc4wc_settings[' . $key . ']';
			if ( 'square_enable_marketing_sync' === $key ) {
				$check_value = get_option( 'square_enable_marketing_sync', 'no' );
			} elseif ( 'square_customer_sync_include_existing' === $key ) {
				$check_value = get_option( 'square_customer_sync_include_existing', 'no' );
			} else {
				$check_value = (string) $value;
			}
			printf(
				'<label><input type="checkbox" name="%1$s" id="shc4wc_%2$s" value="yes" %3$s /> %4$s</label>',
				esc_attr( $input_name ),
				esc_attr( $key ),
				checked( 'yes', $check_value, false ),
				esc_html( isset( $field['label'] ) ? $field['label'] : '' )
			);
		} elseif ( 'password' === $type ) {
			$display_value = ( 'ai_openai_api_key' === $key ) ? '' : (string) $value;
			printf(
				'<input type="password" class="regular-text" name="woocommerce_shc4wc_settings[%1$s]" id="shc4wc_%1$s" value="%2$s" autocomplete="new-password" placeholder="%3$s" />',
				esc_attr( $key ),
				esc_attr( $display_value ),
				( 'ai_openai_api_key' === $key && '' !== trim( (string) $value ) )
					? esc_attr__( 'Key saved — enter new key to replace', 'payments-connect-square' )
					: ''
			);
			if ( 'ai_openai_api_key' === $key && '' !== trim( (string) $value ) ) {
				echo '<p class="description">' . esc_html__( 'OpenAI API key is saved on this server.', 'payments-connect-square' ) . '</p>';
			}
		} else {
			printf(
				'<input type="text" class="regular-text" name="woocommerce_shc4wc_settings[%1$s]" id="shc4wc_%1$s" value="%2$s" />',
				esc_attr( $key ),
				esc_attr( (string) $value )
			);
		}

		if ( ! empty( $field['description_html'] ) ) {
			echo '<p class="description">' . wp_kses_post( (string) $field['description_html'] ) . '</p>';
		} elseif ( ! empty( $field['description'] ) ) {
			echo '<p class="description">' . esc_html( $field['description'] ) . '</p>';
		}
		echo '</td></tr>';
	}

	/**
	 * Inventory sync help text with Square Developer Dashboard link.
	 *
	 * @return string
	 */
	private function get_inventory_sync_description_html() {
		$dashboard = $this->get_square_webhooks_dashboard_link_html();

		return sprintf(
			/* translators: %s: link to Square Developer Dashboard */
			__( 'Requires the webhook URL below in the %s with payment and inventory.count.updated events. Matching products are found by SKU at the selected Square location.', 'payments-connect-square' ),
			$dashboard
		);
	}

	/**
	 * @return string
	 */
	private function get_square_webhooks_dashboard_link_html() {
		return '<a href="https://developer.squareup.com/apps" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Square Developer Dashboard → Webhooks', 'payments-connect-square' ) . '</a>';
	}

	/**
	 * Manual sync button row (no nested form — posts via admin-post link with nonce).
	 *
	 * @return string
	 */
	public static function render_customer_sync_now_row() {
		$enabled   = class_exists( 'SHC4WC_Customer_Sync' ) && SHC4WC_Customer_Sync::is_enabled();
		$connected = SHC4WC_Plugin::has_oauth_connection();
		$can_run   = $enabled && $connected;
		$running   = class_exists( 'SHC4WC_Customer_Sync' ) && SHC4WC_Customer_Sync::is_full_sync_running();
		$include   = class_exists( 'SHC4WC_Customer_Sync' ) && SHC4WC_Customer_Sync::include_existing_on_manual();
		$sync_url  = class_exists( 'SHC4WC_Customer_Sync' )
			? wp_nonce_url( SHC4WC_Customer_Sync::get_manual_sync_url(), 'shc4wc_customer_sync_now' )
			: '#';

		$html  = '<tr valign="top" class="shc4wc-customer-sync-now">';
		$html .= '<th scope="row" class="titledesc">' . esc_html__( 'Manual sync', 'payments-connect-square' ) . '</th>';
		$html .= '<td class="forminp">';

		if ( $can_run ) {
			$html .= '<a class="button button-primary" href="' . esc_url( $sync_url ) . '">';
			$html .= esc_html__( 'Sync customers', 'payments-connect-square' );
			$html .= '</a>';
			$html .= '<p class="description">';
			if ( $running ) {
				$html .= esc_html__( 'Background existing sync is already running (see notice above). This button still runs the recent 1-hour pass.', 'payments-connect-square' );
			} elseif ( $include ) {
				$html .= esc_html__( 'Runs recent customers (last 1 hour), then queues existing customers in the background — based on Include existing above. Save settings first if you just changed that option.', 'payments-connect-square' );
			} else {
				$html .= esc_html__( 'Runs recent customers only (last 1 hour) for the selected direction. Enable Include existing above and save if you also want a full background sync.', 'payments-connect-square' );
			}
			$html .= '</p>';
		} else {
			$html .= '<button type="button" class="button button-primary" disabled="disabled">';
			$html .= esc_html__( 'Sync customers', 'payments-connect-square' );
			$html .= '</button>';
			if ( ! $connected ) {
				$html .= '<p class="description">' . esc_html__( 'Connect Square to enable manual sync.', 'payments-connect-square' ) . '</p>';
			} else {
				$html .= '<p class="description">' . esc_html__( 'Enable Customer sync above and click Save connection settings first.', 'payments-connect-square' ) . '</p>';
			}
		}

		$html .= '</td></tr>';

		return $html;
	}

	/**
	 * Connect / Disconnect Square buttons (no WooCommerce dependency).
	 *
	 * @param string $title Field label.
	 * @return string
	 */
	public static function render_oauth_actions_row( $title ) {
		$connect    = wp_nonce_url( admin_url( 'admin-post.php?action=shc4wc_oauth_start' ), 'shc4wc_oauth_start' );
		$revoke     = wp_nonce_url( admin_url( 'admin-post.php?action=shc4wc_oauth_revoke' ), 'shc4wc_oauth_revoke' );
		$oauth      = SHC4WC_Plugin::get_oauth_data();
		$has_oauth  = SHC4WC_Plugin::has_oauth_connection();
		$active_env = SHC4WC_Plugin::get_current_environment();
		$merch      = SHC4WC_Plugin::is_merchant_connect_ui();

		$html  = '<tr valign="top">';
		$html .= '<th scope="row" class="titledesc">' . esc_html( $title ) . '</th>';
		$html .= '<td class="forminp">';

		foreach ( array( 'live' => __( 'Live', 'payments-connect-square' ), 'sandbox' => __( 'Sandbox', 'payments-connect-square' ) ) as $env_key => $env_label ) {
			$connected = SHC4WC_Plugin::has_oauth_for_environment( $env_key );
			$is_active = ( $env_key === $active_env );
			$status    = $connected
				? __( 'Connected', 'payments-connect-square' )
				: __( 'Not connected', 'payments-connect-square' );
			$html     .= '<p><strong>' . esc_html( $env_label ) . ':</strong> ' . esc_html( $status );
			if ( $is_active ) {
				$html .= ' <em>(' . esc_html__( 'active', 'payments-connect-square' ) . ')</em>';
			}
			$html .= '</p>';
		}

		$html .= '<p class="description">' . esc_html__( 'Connect each environment once. After that, switching Live/Sandbox uses the saved credentials automatically — no disconnect needed.', 'payments-connect-square' ) . '</p>';

		if ( $has_oauth && class_exists( 'SHC4WC_OAuth_Token' ) ) {
			// Token introspection on every Connect page load (Square POST /oauth2/token/status).
			SHC4WC_OAuth_Token::get_token_scopes( $active_env, true );
			$missing = SHC4WC_OAuth_Token::get_missing_scopes( $active_env );
			if ( ! empty( $missing ) ) {
				$missing_list = implode( ', ', array_map( 'strval', $missing ) );
				$html        .= '<div class="notice notice-warning inline" style="margin:12px 0;padding:8px 12px;">';
				$html        .= '<p><strong>' . esc_html__( 'Square connection needs an update.', 'payments-connect-square' ) . '</strong> ';
				$html        .= esc_html__( 'Disconnect Square for this environment, then Connect again so the plugin can request the latest permissions. Without that, some features may not work smoothly.', 'payments-connect-square' );
				$html        .= '</p><p>';
				$html        .= esc_html__( 'Missing scopes (not allowed on this access token):', 'payments-connect-square' );
				$html        .= ' <code>' . esc_html( $missing_list ) . '</code>';
				$html        .= '</p></div>';
			}
		}

		if ( $has_oauth ) {
			$disconnect_label = ( 'live' === $active_env )
				? __( 'Disconnect Square for Live', 'payments-connect-square' )
				: __( 'Disconnect Square for Sandbox', 'payments-connect-square' );
			$html .= '<a class="button" href="' . esc_url( $revoke ) . '">' . esc_html( $disconnect_label ) . '</a> ';
		}
		if ( ! $has_oauth ) {
			$connect_label = ( 'live' === $active_env )
				? __( 'Connect Square for Live', 'payments-connect-square' )
				: __( 'Connect Square for Sandbox', 'payments-connect-square' );
			$html .= '<a class="button button-primary" href="' . esc_url( $connect ) . '">' . esc_html( $connect_label ) . '</a>';

			if ( 'sandbox' === $active_env ) {
				$html .= self::get_sandbox_connect_hint_html();
			}
		}

		if ( ! empty( $oauth['expires_at'] ) ) {
			$html .= '<p><strong>' . esc_html__( 'Access token expires:', 'payments-connect-square' ) . '</strong> ' . esc_html( $oauth['expires_at'] ) . '</p>';
		}
		if ( ! empty( $oauth['token_refreshed_at'] ) ) {
			$html .= '<p><strong>' . esc_html__( 'Token last renewed:', 'payments-connect-square' ) . '</strong> ' . esc_html( $oauth['token_refreshed_at'] ) . '</p>';
		}
		if ( ! $has_oauth && 'sandbox' !== $active_env ) {
			$html .= '<p>' . esc_html(
				$merch
					? __( 'Not connected yet. Click the button to sign in with Square.', 'payments-connect-square' )
					: __( 'Connection status: Not connected. Connect and save selected location.', 'payments-connect-square' )
			) . '</p>';
		}
		$html .= '</td></tr>';

		return $html;
	}

	/**
	 * Read-only webhook URL for Square Developer Dashboard.
	 *
	 * @param string $title Field label.
	 * @return string
	 */
	public static function render_webhook_url_row( $title ) {
		$url       = esc_url( SHC4WC_Plugin::public_api_url( 'shc4wc_webhook' ) );
		$dashboard = '<a href="https://developer.squareup.com/apps" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Square Developer Dashboard → Webhooks', 'payments-connect-square' ) . '</a>';

		$html  = '<tr valign="top">';
		$html .= '<th scope="row" class="titledesc">' . esc_html( $title ) . '</th>';
		$html .= '<td class="forminp"><code>' . esc_html( $url ) . '</code>';
		$html .= '<p class="description">' . wp_kses_post(
			sprintf(
				/* translators: %s: link to Square Developer Dashboard */
				__( 'Add this URL in the %s. Subscribe to payment.updated and inventory.count.updated.', 'payments-connect-square' ),
				$dashboard
			)
		) . '</p>';
		$html .= '</td></tr>';

		return $html;
	}
}
