<?php
/**
 * Settings: single option array, admin-post handlers for save / sync now /
 * test connection. The settings screen itself is rendered by BW_Guides_Admin
 * (admin/views/settings.php).
 */

defined( 'ABSPATH' ) || exit;

class BW_Guides_Settings {

	const OPTION          = 'bw_guides_settings';
	const DEFAULT_HUB_URL = 'https://plugins.bowden.works';

	public function register() {
		add_action( 'admin_post_bw_guides_save_settings', array( $this, 'handle_save' ) );
		add_action( 'admin_post_bw_guides_sync_now', array( $this, 'handle_sync_now' ) );
		add_action( 'admin_post_bw_guides_test_connection', array( $this, 'handle_test_connection' ) );
	}

	/* ------------------------------------------------------------------ */

	public static function get( $key, $default = '' ) {
		$opts = get_option( self::OPTION, array() );
		return isset( $opts[ $key ] ) ? $opts[ $key ] : $default;
	}

	public static function update( $pairs ) {
		$opts = get_option( self::OPTION, array() );
		if ( ! is_array( $opts ) ) {
			$opts = array();
		}
		// autoload=false: holds a bearer key plus churny sync-status fields.
		update_option( self::OPTION, array_merge( $opts, $pairs ), false );
	}

	public static function hub_url() {
		if ( defined( 'BW_GUIDES_HUB_URL' ) && BW_GUIDES_HUB_URL ) {
			return untrailingslashit( (string) BW_GUIDES_HUB_URL );
		}
		$url = (string) self::get( 'hub_url', self::DEFAULT_HUB_URL );
		return untrailingslashit( $url ? $url : self::DEFAULT_HUB_URL );
	}

	public static function site_key() {
		return (string) self::get( 'site_key' );
	}

	/**
	 * HTTPS is required except for local/dev hosts, so the bearer key never
	 * travels in cleartext to a production hub.
	 */
	public static function sanitize_hub_url( $url ) {
		$url = esc_url_raw( trim( (string) $url ) );
		if ( '' === $url ) {
			return '';
		}
		$parts = wp_parse_url( $url );
		if ( empty( $parts['scheme'] ) || empty( $parts['host'] ) ) {
			return null;
		}
		$host   = strtolower( $parts['host'] );
		$is_dev = ( 'localhost' === $host || '127.0.0.1' === $host || preg_match( '/\.(demoing\.info|test|local)$/', $host ) );
		if ( 'https' !== $parts['scheme'] && ! $is_dev ) {
			return null;
		}
		return untrailingslashit( $url );
	}

	/* ------------------------------------------------------------------ */

	public function handle_save() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( 'Insufficient permissions' );
		}
		check_admin_referer( 'bw_guides_save_settings' );

		$notice = 'saved';
		$pairs  = array();

		if ( isset( $_POST['hub_url'] ) ) {
			$hub_url = self::sanitize_hub_url( wp_unslash( $_POST['hub_url'] ) );
			if ( null === $hub_url ) {
				$this->redirect_back( array( 'bw_notice' => 'bad_url' ) );
			}
			$pairs['hub_url'] = $hub_url ? $hub_url : self::DEFAULT_HUB_URL;
		}

		$new_key = false;
		if ( isset( $_POST['site_key'] ) ) {
			$raw = trim( sanitize_text_field( wp_unslash( $_POST['site_key'] ) ) );
			if ( '' !== $raw ) {
				if ( ! preg_match( '/^bwg_\d+_[0-9a-f]{40}$/', $raw ) ) {
					$this->redirect_back( array( 'bw_notice' => 'bad_key' ) );
				}
				$pairs['site_key']      = $raw;
				$pairs['site_key_hint'] = substr( $raw, -6 );
				$new_key                = true;
			}
		}

		if ( ! empty( $_POST['clear_site_key'] ) ) {
			$pairs['site_key']      = '';
			$pairs['site_key_hint'] = '';
			$new_key                = false;
		}

		self::update( $pairs );

		// A new key means the site just got connected — sync immediately.
		if ( $new_key ) {
			$result = ( new BW_Guides_Sync() )->run();
			$notice = is_wp_error( $result ) ? 'key_saved_sync_failed' : 'key_saved_synced';
		}

		$this->redirect_back( array( 'bw_notice' => $notice ) );
	}

	public function handle_sync_now() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( 'Insufficient permissions' );
		}
		check_admin_referer( 'bw_guides_sync_now' );

		$result = ( new BW_Guides_Sync() )->run();
		$this->redirect_back( array( 'bw_notice' => is_wp_error( $result ) ? 'sync_failed' : 'synced' ) );
	}

	public function handle_test_connection() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( 'Insufficient permissions' );
		}
		check_admin_referer( 'bw_guides_test_connection' );

		$client = new BW_Guides_Client();

		$health = $client->health();
		if ( is_wp_error( $health ) ) {
			$this->redirect_back( array( 'bw_notice' => 'hub_unreachable' ) );
		}

		if ( '' === self::site_key() ) {
			$this->redirect_back( array( 'bw_notice' => 'hub_ok_no_key' ) );
		}

		$manifest = $client->manifest();
		if ( is_wp_error( $manifest ) ) {
			$code   = $manifest->get_error_code();
			$notice = ( 'bw_guides_key_revoked' === $code ) ? 'key_revoked' : 'key_invalid';
			$this->redirect_back( array( 'bw_notice' => $notice ) );
		}

		$this->redirect_back( array( 'bw_notice' => 'connection_ok' ) );
	}

	private function redirect_back( $args = array() ) {
		wp_safe_redirect( add_query_arg( $args, admin_url( 'admin.php?page=' . BW_Guides_Admin::SETTINGS_SLUG ) ) );
		exit;
	}
}
