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

class SmallPict_Presigned_Transport {

	/**
	 * Upload file to S3 via Presigned URL.
	 *
	 * Uses direct cURL for streaming — wp_remote_request buffers the entire body into memory,
	 * which causes OOM errors for large files on shared hosting (up to 45MB for Business plan).
	 *
	 * @param string $url          Presigned S3 PUT URL.
	 * @param string $file_path    Absolute path to the file to upload.
	 * @param string $content_type MIME type of the file.
	 * @return true|WP_Error True on success, WP_Error on failure.
	 */
	public function upload_to_s3( $url, $file_path, $content_type ) {
		$file_size = filesize( $file_path );
		if ( false === $file_size ) {
			return new WP_Error( 'file_read_error', 'Could not stat file: ' . $file_path );
		}

		// phpcs:disable WordPress.WP.AlternativeFunctions -- cURL is required for streaming PUT uploads.
		// wp_remote_request() loads the full body into memory, causing OOM on large files.
		$ch = curl_init( $url );
		$fh = fopen( $file_path, 'rb' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
		if ( ! $ch || ! $fh ) {
			return new WP_Error( 'file_read_error', 'Could not open file for streaming: ' . $file_path );
		}

		curl_setopt_array(
			$ch,
			array(
				CURLOPT_PUT            => true,
				CURLOPT_INFILE         => $fh,
				CURLOPT_INFILESIZE     => $file_size,
				CURLOPT_HTTPHEADER     => array( 'Content-Type: ' . $content_type ),
				CURLOPT_RETURNTRANSFER => true,
				CURLOPT_TIMEOUT        => 300,
				CURLOPT_SSL_VERIFYPEER => true,
				CURLOPT_SSL_VERIFYHOST => 2,
			)
		);

		curl_exec( $ch );
		$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
		$curl_err  = curl_error( $ch );
		curl_close( $ch );
		fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
		// phpcs:enable WordPress.WP.AlternativeFunctions

		if ( $curl_err ) {
			return new WP_Error( 'upload_failed', 'cURL error: ' . $curl_err );
		}

		if ( 200 !== $http_code ) {
			return new WP_Error( 'upload_failed', 'S3 Upload Failed with code ' . $http_code );
		}

		return true;
	}

	/**
	 * Download bytes from S3 via Presigned URL
	 */
	public function download_from_s3( $url, $destination_path ) {
		// Use streaming if possible, but wp_remote_get buffers by default.
		// For large files, we might want to use stream=true with a custom handler,
		// but for <50MB `wp_remote_get` is usually fine if PHP memory limit allows.

		$args = array(
			'timeout'   => 300,
			'stream'    => true,
			'filename'  => $destination_path,
			'sslverify' => true, // Default to Secure
		);

		/* Attempt 1: Secure Download */
		$response = wp_remote_get( $url, $args );

		/* Attempt 2: Insecure Fallback (If SSL Error occurs) */
		if ( is_wp_error( $response ) ) {
			$err_msg = $response->get_error_message();
			// Check for curl error 60 (SSL Cert) or general connection errors that might be SSL related
			if ( strpos( $err_msg, 'cURL error 60' ) !== false || strpos( $err_msg, 'certificate' ) !== false ) {
				// error_log("SmallPict Warning: SSL Verification failed ($err_msg). Retrying with sslverify=false.");

				$args['sslverify'] = false;
				$response          = wp_remote_get( $url, $args );
			} else {
				return $response; // Return original error (e.g. timeout)
			}
		}

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

		$code = wp_remote_retrieve_response_code( $response );
		if ( $code !== 200 ) {
			return new WP_Error( 'download_failed', 'S3 Download Failed with code ' . $code );
		}

		return true;
	}
}
