<?php
namespace TeknoTok\AiTranslator\Providers;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use TeknoTok\AiTranslator\Integrations\LicenseManager;
use TeknoTok\AiTranslator\Utils\Logger;

/**
 * TeknoTok Translation Provider implementation.
 * Connects to the central gateway API on soft.teknotok.com.
 */
class TeknoTokProvider implements ProviderInterface {

	/**
	 * Translate text strings or arrays.
	 *
	 * @param string|array $text        String or array to translate.
	 * @param string       $source_lang Source locale.
	 * @param string       $target_lang Target locale.
	 * @return string|array Translated output.
	 * @throws \Exception
	 */
	public function translate( $text, $source_lang, $target_lang ) {
		$settings = get_option( 'teknotok_ait_settings', array() );
		$tone     = $settings['translation_tone'] ?? 'standard';

		$license_data = LicenseManager::get_license_data();
		$license_key  = $license_data['license_key'] ?? '';

		$is_array = is_array( $text );

		$body = array(
			'text'         => $text,
			'source_lang'  => $source_lang,
			'target_lang'  => $target_lang,
			'tone'         => $tone,
			'license_key'  => $license_key,
			'product_slug' => TEKNOTOK_AIT_PRODUCT_SLUG,
			'site_url'     => get_site_url(),
		);

		$max_retries   = 4;
		$response      = null;
		$code          = 0;
		$response_body = '';

		for ( $attempt = 1; $attempt <= $max_retries; $attempt++ ) {
			// Introduce a minor pacing delay (300ms) on the first attempt, or exponential backoff if retrying
			if ( 1 === $attempt ) {
				usleep( 300000 );
			} else {
				// Exponential backoff with jitter: 2s, 4s, 8s (+ random 0-500ms)
				$delay = ( pow( 2, $attempt - 1 ) * 1 ) + ( rand( 0, 500 ) / 1000 );
				usleep( $delay * 1000000 );
			}

			$response = $this->request_gateway( $body );

			if ( ! is_wp_error( $response ) ) {
				$code          = wp_remote_retrieve_response_code( $response );
				$response_body = wp_remote_retrieve_body( $response );
				if ( 200 === $code ) {
					break; // Success!
				}

				// Check for permanent client-side errors (400 to 499, except 429 which is rate limit)
				if ( $code >= 400 && $code < 500 && 429 !== $code ) {
					break; // Stop retrying on permanent failures (e.g. quota exceeded 402, invalid key 403, missing field 400)
				}

				if ( $code >= 500 && ( false !== stripos( $response_body, 'cURL error 28' ) || false !== stripos( $response_body, 'timed out' ) ) ) {
					break;
				}
			}
		}

		if ( is_wp_error( $response ) ) {
			Logger::log( $response->get_error_message(), 'error' );
			throw new \Exception( $response->get_error_message() );
		}

		if ( 200 !== $code ) {
			$error_data = json_decode( $response_body, true );
			$msg = $error_data['message'] ?? sprintf( __( 'Translation request failed with code %d', 'teknotok-ai-translator-pro' ), $code );
			Logger::log( $msg, 'error' );
			throw new \Exception( $msg, $code );
		}

		$data = json_decode( $response_body, true );
		if ( empty( $data ) || ! isset( $data['success'] ) || ! $data['success'] ) {
			$msg = $data['message'] ?? __( 'Failed to retrieve valid translation from gateway.', 'teknotok-ai-translator-pro' );
			throw new \Exception( $msg );
		}

		$translated = $data['translation'] ?? '';

		if ( empty( $translated ) ) {
			throw new \Exception( __( 'Received empty translation response from gateway.', 'teknotok-ai-translator-pro' ) );
		}

		if ( $is_array ) {
			if ( ! is_array( $translated ) ) {
				Logger::log( 'Failed parsing gateway translation array response: ' . wp_json_encode( $translated ), 'error' );
				throw new \Exception( __( 'Gateway did not return a valid translation mapping.', 'teknotok-ai-translator-pro' ) );
			}
			return $translated;
		}

		return trim( $translated );
	}

	/**
	 * Send a translation request to the configured gateway.
	 *
	 * @param array $body Request body.
	 * @return array|\WP_Error HTTP-like response.
	 */
	private function request_gateway( $body ) {
		if ( $this->can_use_local_gateway() ) {
			$request = new \WP_REST_Request( 'POST', '/teknotok-translator/v1/translate' );
			foreach ( $body as $key => $value ) {
				$request->set_param( $key, $value );
			}

			$response = \TKNTK_LM_REST::translate( $request );
			if ( $response instanceof \WP_REST_Response ) {
				return array(
					'response' => array( 'code' => $response->get_status() ),
					'body'     => wp_json_encode( $response->get_data() ),
				);
			}
		}

		return wp_remote_post(
			TEKNOTOK_AIT_TRANSLATE_API,
			array(
				'headers' => array(
					'Content-Type' => 'application/json',
				),
				'body'    => wp_json_encode( $body ),
				'timeout' => 75,
			)
		);
	}

	/**
	 * Check whether the gateway is the same WordPress install as this plugin.
	 *
	 * @return bool True when local dispatch is available.
	 */
	private function can_use_local_gateway() {
		if ( ! class_exists( '\TKNTK_LM_REST' ) || ! class_exists( '\WP_REST_Request' ) ) {
			return false;
		}

		$gateway = wp_parse_url( TEKNOTOK_AIT_GATEWAY_BASE_URL );
		$home    = wp_parse_url( home_url() );

		if ( empty( $gateway['host'] ) || empty( $home['host'] ) || strtolower( $gateway['host'] ) !== strtolower( $home['host'] ) ) {
			return false;
		}

		$gateway_port = isset( $gateway['port'] ) ? (int) $gateway['port'] : null;
		$home_port    = isset( $home['port'] ) ? (int) $home['port'] : null;

		return $gateway_port === $home_port;
	}

	/**
	 * Test key by sending a cheap request.
	 *
	 * @return bool
	 */
	public function validate_key() {
		try {
			$this->translate( 'Test', 'en', 'es' );
			return true;
		} catch ( \Exception $e ) {
			return false;
		}
	}

	/**
	 * Check if provider is configured (e.g. API credentials are set).
	 *
	 * @return bool True if configured, false otherwise.
	 */
	public function is_configured() {
		// The gateway provider is built-in and always available, no credentials setup is required
		return true;
	}
}
