<?php
/**
 * PhotoShelter Remote Client abstract class.
 *
 * @package photoshelter-importer
 */

namespace PhotoShelter\Importer\API;

/**
 * Class Abstract RemoteSource
 */
abstract class ClientRemote {
	/**
	 * Data source instance.
	 *
	 * @var RemoteSource
	 */
	protected $data_source;

	/**
	 * Client constructor.
	 *
	 * @param RemoteSource $data_source RemoteSource instance.
	 *
	 * @since 1.0.0
	 */
	public function __construct( RemoteSource $data_source ) {
		$this->data_source = $data_source;
	}

	/**
	 * Get the DataSource instance.
	 *
	 * @return RemoteSource
	 * @since 1.0.0
	 */
	public function get_data_source() {
		return $this->data_source;
	}

	/**
	 * Handle response from wp_remote_request().
	 *
	 * @param array   $response Response array.
	 * @param boolean $decode_json Whether to decode JSON (default = true).
	 *
	 * @return mixed|\WP_Error
	 * @since 1.0.0
	 */
	protected function handle_response( $response, $decode_json = true ) {
		if ( true === is_wp_error( $response ) ) {
			return $response;
		}

		$raw_body      = wp_remote_retrieve_body( $response );
		$response_body = $raw_body;

		if ( true === $decode_json ) {
			$response_body = json_decode( $raw_body );
		}

		$response_code = wp_remote_retrieve_response_code( $response );

		// Debug logging for non-200 responses.
		if ( 200 !== $response_code ) {
			$this->log_api_error( $response_code, $raw_body, $response_body, $response );
		}

		switch ( $response_code ) {
			case 200:
				return $response_body;
			case 400: // Bad request.
			case 401: // Unauthorized.
			case 403: // Forbidden.
			case 404: // Not found.
			case 500: // Malformed request.
			default:
				$error_message = $this->extract_error_message( $response_body, $raw_body );

				return new \WP_Error(
					'photoshelter-api-bad-response',
					sprintf(
						/* translators: %1$d: Numeric HTTP status code (e.g. 400, 403, 500, etc.), %2$s Error message, if any. */
						__( 'Bad response from API (%1$d): %2$s', 'photoshelter-importer' ),
						$response_code,
						$error_message
					),
					$response_body
				);
		}
	}

	/**
	 * Extract error message from API response.
	 *
	 * Safely extracts error message from various response formats.
	 *
	 * @since 1.3.0
	 *
	 * @param mixed  $response_body Decoded response body.
	 * @param string $raw_body      Raw response body string.
	 * @return string Error message.
	 */
	protected function extract_error_message( $response_body, $raw_body ) {
		// Try standard PhotoShelter API error format: { errors: [{ title: "..." }] }.
		if ( true === is_object( $response_body ) && true === isset( $response_body->errors ) && true === is_array( $response_body->errors ) ) {
			$first_error = $response_body->errors[0] ?? null;
			if ( true === is_object( $first_error ) && true === isset( $first_error->title ) ) {
				// Check for permission errors and provide user-friendly messages.
				$error_id = true === isset( $first_error->id ) ? $first_error->id : '';
				return $this->get_user_friendly_error_message( $error_id, $first_error->title );
			}
		}

		// Try alternative error format: { error: "..." }.
		if ( true === is_object( $response_body ) && true === isset( $response_body->error ) ) {
			return true === is_string( $response_body->error ) ? $response_body->error : wp_json_encode( $response_body->error );
		}

		// Try alternative format: { message: "..." }.
		if ( true === is_object( $response_body ) && true === isset( $response_body->message ) ) {
			return $response_body->message;
		}

		// If response body is a string, use it directly (truncated).
		if ( true === is_string( $response_body ) && false === empty( $response_body ) ) {
			return substr( $response_body, 0, 200 );
		}

		// Fallback to raw body (truncated).
		if ( false === empty( $raw_body ) ) {
			return substr( $raw_body, 0, 200 );
		}

		return __( 'Unknown error', 'photoshelter-importer' );
	}

	/**
	 * Convert PhotoShelter API error IDs to user-friendly messages.
	 *
	 * @since 1.3.0
	 *
	 * @param string $error_id    The error ID from the API response.
	 * @param string $error_title The original error title/message.
	 * @return string User-friendly error message.
	 */
	protected function get_user_friendly_error_message( $error_id, $error_title ) {
		$user_friendly_messages = array(
			'AcsPermissionException'    => __( 'You do not have permission to download this file in the requested format. Please check your PhotoShelter account permissions or try a different download quality.', 'photoshelter-importer' ),
			'AuthenticationException'   => __( 'Your PhotoShelter session has expired. Please re-authenticate in the plugin settings.', 'photoshelter-importer' ),
			'AuthorizationException'    => __( 'You are not authorized to access this resource. Please check your PhotoShelter account permissions.', 'photoshelter-importer' ),
			'ResourceNotFoundException' => __( 'The requested media could not be found in PhotoShelter. It may have been deleted or moved.', 'photoshelter-importer' ),
			'RateLimitException'        => __( 'Too many requests to PhotoShelter. Please wait a moment and try again.', 'photoshelter-importer' ),
		);

		if ( true === isset( $user_friendly_messages[ $error_id ] ) ) {
			return $user_friendly_messages[ $error_id ];
		}

		return $error_title;
	}

	/**
	 * Log API error details for debugging.
	 *
	 * @since 1.3.0
	 *
	 * @param int    $response_code HTTP response code.
	 * @param string $raw_body      Raw response body.
	 * @param mixed  $decoded_body  Decoded response body.
	 * @param array  $response      Full response array from wp_remote_request.
	 * @return void
	 */
	protected function log_api_error( $response_code, $raw_body, $decoded_body, $response ) {
		// Only log if WP_DEBUG is enabled.
		if ( false === defined( 'WP_DEBUG' ) || true !== WP_DEBUG ) {
			return;
		}

		$request_url = $this->extract_request_url( $response );
		$headers     = wp_remote_retrieve_headers( $response );
		$header_data = true === is_object( $headers ) && true === method_exists( $headers, 'getAll' ) ? $headers->getAll() : (array) $headers;

		// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r
		error_log( '=== PhotoShelter API Error Debug ===' );
		error_log( 'Response Code: ' . $response_code );
		error_log( 'Request URL: ' . $request_url );
		error_log( 'Raw Body: ' . substr( $raw_body, 0, 1000 ) );
		error_log( 'Decoded Body Type: ' . gettype( $decoded_body ) );
		error_log( 'Decoded Body: ' . print_r( $decoded_body, true ) );
		error_log( 'Response Headers: ' . print_r( $header_data, true ) );
		error_log( '=== End PhotoShelter API Error Debug ===' );
		// phpcs:enable WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r
	}

	/**
	 * Extract request URL from response object.
	 *
	 * @since 1.3.0
	 *
	 * @param array $response Response array from wp_remote_request.
	 * @return string Request URL or 'unknown'.
	 */
	protected function extract_request_url( $response ) {
		// Try to get URL from http_response object.
		if ( true === isset( $response['http_response'] ) && true === is_object( $response['http_response'] ) ) {
			if ( true === method_exists( $response['http_response'], 'get_response_object' ) ) {
				$response_object = $response['http_response']->get_response_object();
				if ( true === is_object( $response_object ) && true === isset( $response_object->url ) ) {
					return $response_object->url;
				}
			}
		}

		return 'unknown';
	}
}
