<?php
/**
 * REST controller: /wp-json/bw/v1/update-check
 */

defined( 'ABSPATH' ) || exit;

class BW_Update_Server_REST {

	const NAMESPACE = 'bw/v1';

	public function register() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	public function register_routes() {
		register_rest_route(
			self::NAMESPACE,
			'/update-check',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'handle_update_check' ),
				'permission_callback' => '__return_true',
				'args'                => array(
					'slug'    => array(
						'type'              => 'string',
						'required'          => true,
						'sanitize_callback' => 'sanitize_key',
					),
					'version' => array(
						'type'              => 'string',
						'required'          => false,
						'sanitize_callback' => 'sanitize_text_field',
					),
				),
			)
		);

		register_rest_route(
			self::NAMESPACE,
			'/plugins',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'handle_plugins_list' ),
				'permission_callback' => '__return_true',
			)
		);

		register_rest_route(
			self::NAMESPACE,
			'/health',
			array(
				'methods'             => WP_REST_Server::READABLE,
				'callback'            => array( $this, 'handle_health' ),
				'permission_callback' => '__return_true',
			)
		);
	}

	public function handle_update_check( WP_REST_Request $request ) {
		$slug = $request->get_param( 'slug' );

		$manifest = BW_Update_Server_Manifest::latest( $slug );
		if ( is_wp_error( $manifest ) ) {
			return $manifest;
		}

		// Log the check.
		$installed_version = (string) $request->get_param( 'version' );
		$this->log_request( $slug, $installed_version, $manifest['version'] ?? '', $request );

		return rest_ensure_response( $manifest );
	}

	public function handle_plugins_list() {
		$slugs = BW_Update_Server_Manifest::list_slugs();
		$out   = array();
		foreach ( $slugs as $slug ) {
			$m = BW_Update_Server_Manifest::latest( $slug );
			if ( ! is_wp_error( $m ) ) {
				$out[] = array(
					'slug'    => $slug,
					'name'    => $m['name'] ?? $slug,
					'version' => $m['version'] ?? '',
				);
			}
		}
		return rest_ensure_response( $out );
	}

	public function handle_health() {
		return rest_ensure_response(
			array(
				'status'  => 'ok',
				'version' => BW_UPDATE_SERVER_VERSION,
				'time'    => current_time( 'mysql', 1 ),
			)
		);
	}

	private function log_request( $slug, $installed_version, $latest_version, WP_REST_Request $request ) {
		$ua = (string) $request->get_header( 'user_agent' );

		// Extract site URL from WordPress User-Agent, which has format:
		// "WordPress/6.5.2; https://example.com"
		$site_url = '';
		if ( preg_match( '#WordPress/[^;]+;\s*(https?://[^\s;]+)#i', $ua, $m ) ) {
			$site_url = esc_url_raw( $m[1] );
		}

		$wp_version  = '';
		$php_version = '';
		if ( preg_match( '#WordPress/([0-9.]+)#i', $ua, $m ) ) {
			$wp_version = $m[1];
		}

		BW_Update_Server_Repository::log_check(
			array(
				'plugin_slug'       => $slug,
				'site_url'          => $site_url,
				'installed_version' => substr( (string) $installed_version, 0, 32 ),
				'latest_version'    => substr( (string) $latest_version, 0, 32 ),
				'wp_version'        => substr( $wp_version, 0, 32 ),
				'php_version'       => substr( $php_version, 0, 32 ),
				'ip_address'        => $this->get_client_ip(),
				'user_agent'        => substr( $ua, 0, 500 ),
			)
		);
	}

	private function get_client_ip() {
		// Trust CF-Connecting-IP if the request came through Cloudflare (Caddy sets this).
		$headers = array( 'HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR' );
		foreach ( $headers as $h ) {
			if ( ! empty( $_SERVER[ $h ] ) ) {
				$ip = sanitize_text_field( wp_unslash( $_SERVER[ $h ] ) );
				// Take first IP if there's a list.
				$ip = trim( explode( ',', $ip )[0] );
				if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
					return $ip;
				}
			}
		}
		return '';
	}
}
