<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class SftcyWordaiHostedServicesClient {
	const INSTALLATION_ID_OPTION     = 'sftcy_wordai_service_installation_id';
	const INSTALLATION_SECRET_OPTION = 'sftcy_wordai_service_installation_secret';
	const CAPABILITIES_TRANSIENT     = 'sftcy_wordai_service_capabilities';

	public static function api_base() {
		$base = defined( 'SFTCY_SOFTCOY_API_BASE' ) ? SFTCY_SOFTCOY_API_BASE : 'https://softcoy.com/api/v1';
		return untrailingslashit( (string) apply_filters( 'sftcy_wordai_hosted_services_api_base', $base ) );
	}

	public static function request( $method, $path, $payload = array(), $retry_registration = true ) {
		$method = strtoupper( sanitize_key( $method ) );
		$path   = '/' . ltrim( (string) $path, '/' );

		if ( ! self::has_identity() ) {
			$registration = self::register();

			if ( is_wp_error( $registration ) ) {
				return $registration;
			}
		}

		$url       = self::api_base() . $path;
		$body      = empty( $payload ) ? '' : wp_json_encode( $payload );
		$timestamp = (string) time();
		$nonce     = wp_generate_password( 24, false, false );
		$url_path  = (string) wp_parse_url( $url, PHP_URL_PATH );
		$api_offset = strpos( $url_path, '/api/' );
		if ( false !== $api_offset ) {
			$url_path = substr( $url_path, $api_offset );
		}
		$canonical = implode( "
", array( $method, $url_path, $timestamp, $nonce, hash( 'sha256', $body ) ) );
		$signature = hash_hmac( 'sha256', $canonical, (string) get_option( self::INSTALLATION_SECRET_OPTION, '' ) );
		$args      = array(
			'method'      => $method,
			'timeout'     => 20,
			'redirection' => 2,
			'headers'     => array(
				'Accept'                 => 'application/json',
				'Content-Type'           => 'application/json',
				'X-Softcoy-Installation' => (string) get_option( self::INSTALLATION_ID_OPTION, '' ),
				'X-Softcoy-Timestamp'    => $timestamp,
				'X-Softcoy-Nonce'        => $nonce,
				'X-Softcoy-Signature'    => $signature,
			),
		);

		if ( '' !== $body ) {
			$args['body'] = $body;
		}

		$response = wp_remote_request( $url, $args );

		if ( is_wp_error( $response ) ) {
			return new WP_Error( 'wordai_service_unavailable', __( 'SOFTCOY hosted services could not be reached.', SFTCY_WORDAI_TEXT_DOMAIN ), $response->get_error_message() );
		}

		$status = (int) wp_remote_retrieve_response_code( $response );
		$data   = json_decode( (string) wp_remote_retrieve_body( $response ), true );
		$data   = is_array( $data ) ? $data : array();

		if ( 401 === $status && $retry_registration ) {
			self::clear_identity();
			return self::request( $method, $path, $payload, false );
		}

		if ( $status < 200 || $status >= 300 ) {
			$message = self::safe_error_message(
				$status,
				$data,
				__( 'SOFTCOY returned an unexpected service response.', SFTCY_WORDAI_TEXT_DOMAIN )
			);
			return new WP_Error( ! empty( $data['code'] ) ? sanitize_key( $data['code'] ) : 'wordai_service_error', $message, array( 'status' => $status, 'response' => $data ) );
		}

		return $data;
	}

	public static function register() {
		$edition = defined( 'WORDAI_PRODUCT_TIER' ) && 'pro' === WORDAI_PRODUCT_TIER ? 'pro' : 'free';
		$payload = array(
			'plugin_slug'      => 'pro' === $edition ? 'wordai-pro' : 'wordai',
			'plugin_edition'   => $edition,
			'plugin_version'   => defined( 'SFTCY_WORDAI_VERSION' ) ? SFTCY_WORDAI_VERSION : '',
			'site_url'         => home_url( '/' ),
			'admin_email'      => sanitize_email( (string) get_option( 'admin_email', '' ) ),
			'marketing_opt_in' => (bool) get_option( 'sftcy_wordai_search_console_marketing_opt_in', false ),
		);

		if ( 'pro' === $edition ) {
			$license_key = sanitize_text_field( (string) get_option( 'softcoy_wordai_pro_license_key', '' ) );
			if ( '' !== $license_key ) {
				$payload['license_key'] = $license_key;
			}
		}

		$response = wp_remote_post(
			self::api_base() . '/plugin-installations/register',
			array(
				'timeout' => 20,
				'headers' => array( 'Accept' => 'application/json', 'Content-Type' => 'application/json' ),
				'body'    => wp_json_encode( $payload ),
			)
		);

		if ( is_wp_error( $response ) ) {
			return new WP_Error( 'wordai_registration_unavailable', __( 'SOFTCOY could not register this WordAI installation.', SFTCY_WORDAI_TEXT_DOMAIN ), $response->get_error_message() );
		}

		$status = (int) wp_remote_retrieve_response_code( $response );
		$data   = json_decode( (string) wp_remote_retrieve_body( $response ), true );

		if ( $status < 200 || $status >= 300 || empty( $data['installation_id'] ) || empty( $data['installation_secret'] ) ) {
			return new WP_Error(
				'wordai_registration_failed',
				self::safe_error_message(
					$status,
					is_array( $data ) ? $data : array(),
					__( 'SOFTCOY did not return a valid installation identity.', SFTCY_WORDAI_TEXT_DOMAIN )
				)
			);
		}

		update_option( self::INSTALLATION_ID_OPTION, sanitize_text_field( $data['installation_id'] ), false );
		update_option( self::INSTALLATION_SECRET_OPTION, sanitize_text_field( $data['installation_secret'] ), false );

		if ( ! empty( $data['entitlement'] ) && is_array( $data['entitlement'] ) ) {
			set_transient( self::CAPABILITIES_TRANSIENT, $data['entitlement'], HOUR_IN_SECONDS );
		}

		return $data;
	}

	public static function capabilities( $refresh = false ) {
		if ( ! $refresh ) {
			$cached = get_transient( self::CAPABILITIES_TRANSIENT );
			if ( is_array( $cached ) ) {
				return $cached;
			}
		}

		$data = self::request( 'GET', '/services/capabilities' );
		if ( ! is_wp_error( $data ) ) {
			set_transient( self::CAPABILITIES_TRANSIENT, $data, HOUR_IN_SECONDS );
		}
		return $data;
	}

	public static function has_identity() {
		return '' !== (string) get_option( self::INSTALLATION_ID_OPTION, '' )
			&& '' !== (string) get_option( self::INSTALLATION_SECRET_OPTION, '' );
	}

	public static function clear_identity() {
		delete_option( self::INSTALLATION_ID_OPTION );
		delete_option( self::INSTALLATION_SECRET_OPTION );
		delete_transient( self::CAPABILITIES_TRANSIENT );
	}

	private static function safe_error_message( $status, $data, $fallback ) {
		$message = ! empty( $data['message'] ) ? sanitize_text_field( (string) $data['message'] ) : (string) $fallback;

		if (
			404 === (int) $status
			|| preg_match( '/\\b(route|api\\/v\\d+|\\/api\\/|endpoint)\\b/i', $message )
			|| false !== strpos( $message, 'services/search-console' )
		) {
			return __( 'SOFTCOY hosted services are temporarily unavailable. Please try again later or contact support if this continues.', SFTCY_WORDAI_TEXT_DOMAIN );
		}

		return $message;
	}
}
