<?php
/**
 * Abstract image provider.
 *
 * @package CatalogPilot\AiStudio
 */

namespace CatalogPilot\AiStudio\Providers;

defined( 'ABSPATH' ) || exit;

abstract class Image_Provider {

	protected $api_key;
	protected $model;

	public function __construct( $api_key, $model = '' ) {
		$this->api_key = (string) $api_key;
		$this->model   = (string) $model;
	}

	abstract public function id();

	/**
	 * Generate one or more images.
	 *
	 * @param string $prompt Prompt text.
	 * @param array  $opts   { size|aspect_ratio, count, negative_prompt, seed, quality, style }
	 * @return array|\WP_Error Array of [ [ 'bytes' => binary, 'mime' => string ], ... ]
	 */
	abstract public function generate( $prompt, array $opts = array() );

	abstract public function test_connection();

	protected function post_json( $url, $body, $headers = array() ) {
		$headers = wp_parse_args( $headers, array( 'Content-Type' => 'application/json' ) );
		$args = array(
			'timeout' => 120,
			'headers' => $headers,
			'body'    => wp_json_encode( $body ),
		);

		$max_retries = 3;
		$attempt     = 0;
		$last_error  = null;

		while ( $attempt < $max_retries ) {
			$response = wp_remote_post( $url, $args );
			if ( is_wp_error( $response ) ) {
				$last_error = $response;
				sleep( min( 30, pow( 2, $attempt ) ) );
				$attempt++;
				continue;
			}
			$code = wp_remote_retrieve_response_code( $response );
			if ( 429 === $code || ( $code >= 500 && $code < 600 ) ) {
				$retry_after = (int) wp_remote_retrieve_header( $response, 'retry-after' );
				$wait        = $retry_after > 0 ? min( 60, $retry_after ) : min( 30, pow( 2, $attempt ) );
				$last_error  = self::handle_response( $response );
				sleep( $wait );
				$attempt++;
				continue;
			}
			return self::handle_response( $response );
		}

		return $last_error ?: new \WP_Error( 'cpais_image_error', __( 'Image request failed after retries.', 'catalogpilot-ai-studio-for-woocommerce' ) );
	}

	protected static function handle_response( $response ) {
		if ( is_wp_error( $response ) ) {
			return $response;
		}
		$code = wp_remote_retrieve_response_code( $response );
		$body = wp_remote_retrieve_body( $response );
		$json = json_decode( $body, true );
		if ( $code < 200 || $code >= 300 ) {
			$message = '';
			if ( is_array( $json ) ) {
				$message = $json['error']['message']
					?? $json['message']
					?? ( is_array( $json['error'] ?? null ) ? wp_json_encode( $json['error'] ) : '' );
			}
			if ( '' === $message ) {
				$message = sprintf( 'HTTP %d', $code );
			}
			return new \WP_Error( 'cpais_image_error', $message, array( 'status' => $code ) );
		}
		return $json ?? array( '_raw' => $body );
	}

	protected static function fetch_url_bytes( $url ) {
		$response = wp_remote_get( $url, array( 'timeout' => 60 ) );
		if ( is_wp_error( $response ) ) {
			return $response;
		}
		$code = wp_remote_retrieve_response_code( $response );
		if ( $code < 200 || $code >= 300 ) {
			return new \WP_Error( 'cpais_image_download', sprintf( 'Download failed (%d)', $code ) );
		}
		$bytes = wp_remote_retrieve_body( $response );
		$mime  = wp_remote_retrieve_header( $response, 'content-type' );
		return array( 'bytes' => $bytes, 'mime' => $mime ?: 'image/png' );
	}
}

function cpais_image_factory( $provider_id, $api_key, $model = '' ) {
	switch ( $provider_id ) {
		case 'openai':
			return new Image_OpenAI_Provider( $api_key, $model );
		case 'replicate':
			return new Image_Replicate_Provider( $api_key, $model );
		case 'gemini':
			return new Image_Gemini_Provider( $api_key, $model );
		case 'stability':
			return new Image_Stability_Provider( $api_key, $model );
	}
	return new \WP_Error( 'cpais_unknown_image_provider', __( 'Unknown image provider.', 'catalogpilot-ai-studio-for-woocommerce' ) );
}

function cpais_image_providers_definitions() {
	return array(
		'openai' => array(
			'label'   => 'OpenAI',
			'models'  => array( 'gpt-image-1', 'dall-e-3', 'dall-e-2' ),
			'sizes'   => array( '1024x1024', '1024x1536', '1536x1024', '1792x1024', '1024x1792' ),
			'has_key_field' => true,
		),
		'replicate' => array(
			'label'   => 'Replicate',
			'models'  => array(
				'black-forest-labs/flux-schnell',
				'black-forest-labs/flux-dev',
				'black-forest-labs/flux-1.1-pro',
				'stability-ai/sdxl',
				'bytedance/sdxl-lightning-4step',
				'ideogram-ai/ideogram-v2',
				'recraft-ai/recraft-v3',
			),
			'sizes'   => array( '1:1', '16:9', '9:16', '3:4', '4:3', '3:2', '2:3' ),
			'has_key_field' => true,
		),
		'gemini' => array(
			'label'   => 'Google Gemini',
			'models'  => array( 'imagen-3.0-generate-002', 'imagen-4.0-generate-001', 'imagen-4.0-ultra-generate-001' ),
			'sizes'   => array( '1:1', '16:9', '9:16', '4:3', '3:4' ),
			'has_key_field' => true,
		),
		'stability' => array(
			'label'   => 'Stability AI',
			'models'  => array(
				'stable-diffusion-xl-1024-v1-0',
				'stable-diffusion-v1-6',
			),
			'sizes'   => array( '1024x1024', '1152x896', '896x1152', '1344x768', '768x1344' ),
			'has_key_field' => true,
		),
	);
}
