<?php

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

class R123_WC_API_Client {
	private const BLOCKED_UNTIL_OPTION = 'r123_wc_api_blocked_until';
	private const LAST_ERROR_OPTION    = 'r123_wc_api_last_error';

	public function is_configured(): bool {
		$url     = (string) R123_WC_Settings::get('webhook_url', '');
		$api_key = (string) R123_WC_Settings::get('api_key', '');

		return $url !== '' && $api_key !== '';
	}

	public function test_configuration(): array {
		if (!$this->is_configured()) {
			throw new RuntimeException('Webhook URL or API key is not configured.');
		}

		return [
			'message' => 'Configuration values are present.',
		];
	}

	public function send_order(array $payload): array {
		if (!$this->is_configured()) {
			throw new RuntimeException('Webhook URL or API key is not configured.');
		}

		if ($this->is_temporarily_blocked()) {
			throw new RuntimeException('Connection is temporarily blocked because of previous API errors.');
		}

		$url     = (string) R123_WC_Settings::get('webhook_url', '');
		$api_key = (string) R123_WC_Settings::get('api_key', '');

		$body = wp_json_encode($payload);

		if ($body === false) {
			throw new RuntimeException('Failed to encode JSON payload.');
		}

		$response = wp_remote_post(
			$url,
			[
				'timeout' => 20,
				'headers' => [
					'Content-Type'  => 'application/json',
					'Accept'        => 'application/json',
					'x-api-key'     => $api_key,
					'X-R123-Source' => 'racun123-woocommerce-plugin',
					'User-Agent'    => 'Racun123-WooCommerce/' . R123_WC_VERSION,
				],
				'body' => $body,
			]
		);

		if (is_wp_error($response)) {
			$error_message = sanitize_text_field($response->get_error_message());
			$this->register_api_failure($error_message);

			throw new RuntimeException(esc_html($error_message));
		}

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

		/**
		 * HARD ERROR (HTTP level)
		 */
		if ($code < 200 || $code >= 300) {
			$message = 'HTTP ' . $code;

			if (is_array($data) && !empty($data['error'])) {
				$message .= ': ' . sanitize_text_field((string) $data['error']);
			} elseif ($raw_body !== '') {
				$message .= ': ' . sanitize_text_field(wp_strip_all_tags($raw_body));
			}

			$this->register_api_failure($message);

			throw new RuntimeException(esc_html($message));
		}

		/**
		 * Normalize response
		 */
		$received       = !empty($data['received']);
		$invoice_id     = isset($data['invoiceId']) ? sanitize_text_field((string) $data['invoiceId']) : '';
		$invoice_number = isset($data['invoiceNumber']) ? sanitize_text_field((string) $data['invoiceNumber']) : '';
		$pdf_url        = isset($data['pdfUrl']) ? esc_url_raw((string) $data['pdfUrl']) : '';
		$business_error = isset($data['error']) ? sanitize_text_field((string) $data['error']) : '';

		/**
		 * Business logic error (VERY IMPORTANT)
		 * HTTP 200 but still failed (e.g. fiscalization)
		 */
		if (!empty($business_error)) {
			$this->register_api_failure($business_error);
		} else {
			$this->clear_api_error_state();
		}

		/**
		 * Fallback if response is weird
		 */
		if (!$received && empty($invoice_id)) {
			throw new RuntimeException('Invalid API response structure.');
		}

		return [
			'received'      => $received,
			'invoiceId'     => $invoice_id,
			'invoiceNumber' => $invoice_number,
			'pdfUrl'        => $pdf_url,
			'error'         => $business_error,
		];
	}

	public function is_temporarily_blocked(): bool {
		$blocked_until = (int) get_option(self::BLOCKED_UNTIL_OPTION, 0);

		return $blocked_until > time();
	}

	public function get_blocked_until(): int {
		return (int) get_option(self::BLOCKED_UNTIL_OPTION, 0);
	}

	public function get_last_error(): string {
		return (string) get_option(self::LAST_ERROR_OPTION, '');
	}

	public function clear_api_error_state(): void {
		delete_option(self::BLOCKED_UNTIL_OPTION);
		delete_option(self::LAST_ERROR_OPTION);
	}

	private function register_api_failure(string $message): void {
		$clean_message = sanitize_text_field(wp_strip_all_tags($message));

		update_option(self::LAST_ERROR_OPTION, $clean_message, false);
		update_option(self::BLOCKED_UNTIL_OPTION, time() + 300, false);
	}
}