<?php

namespace Repetito\Admin;

// If this file is called directly, abort.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use Repetito\Traits\OrderUtils;
use Repetito\Traits\Singleton;

use const Repetito\API_URL;
use const Repetito\VERSION;


final class RepetitoApi {

	use Singleton;
	use OrderUtils;

	/**
	 * Anonymize a string by replacing all but the last 2 characters with asterisks
	 *
	 * @param string $value The value to anonymize
	 * @return string Anonymized value
	 */
	private function anonymizeValue( $value ) {
		if ( empty( $value ) || strlen( $value ) <= 2 ) {
			return str_repeat( '*', strlen( $value ) );
		}
		$last_two = substr( $value, -2 );
		$asterisks = str_repeat( '*', strlen( $value ) - 2 );
		return $asterisks . $last_two;
	}

	/**
	 * Triggers API call
	 * @return void
	 */
	public function registerOrder( $order_id ) {
		$order   = wc_get_order( $order_id );
		$settings = get_option( 'repetito-settings' );
		$api_key = isset($settings['api_key']) ? (string) $settings['api_key'] : '';
		$anonymize = isset($settings['privacy_anonymize_data']) ? (bool) $settings['privacy_anonymize_data'] : false;

		// bail if no API selected
		if ( false === $order ) {
			return;
		}

		// bail if no API key
		if ( '' === $api_key ) {
			return;
		}

		// find out if this order has repetito fee added
		$has_repetito_fee = $this->orderHasFee( $order );

		// post to api via Guzzle
		if ( $has_repetito_fee ) {
			$body = array(
				'orderNumber'  => (string) $order_id,
				'emailAddress' => (string) $order->get_billing_email(),
			);

			// Add phone number (anonymized if setting is enabled)
			$phone = '';
			if ( $order->get_billing_phone() !== '' ) {
				$phone = $order->get_billing_phone();
			} elseif ( $order->get_shipping_phone() !== '' ) {
				$phone = $order->get_shipping_phone();
			}

			if ( $phone !== '' ) {
				$body['phoneNumber'] = $anonymize ? $this->anonymizeValue( $phone ) : $phone;
			}

			// Add billing address (anonymized if setting is enabled)
			if ( $order->has_billing_address() ) {
				$street = $order->get_billing_address_1() . $order->get_billing_address_2();
				$town = $order->get_billing_city();
				$postCode = $order->get_billing_postcode();
				$country = $order->get_billing_country();

				$body['billingAddress'] = array(
					'street'   => $anonymize ? $this->anonymizeValue( $street ) : $street,
					'town'     => $anonymize ? $this->anonymizeValue( $town ) : $town,
					'postCode' => $anonymize ? $this->anonymizeValue( $postCode ) : $postCode,
					'country'  => $anonymize ? $this->anonymizeValue( $country ) : $country,
				);
			}

			// Add shipping address (anonymized if setting is enabled)
			if ( $order->has_shipping_address() ) {
				$street = $order->get_shipping_address_1() . $order->get_shipping_address_2();
				$town = $order->get_shipping_city();
				$postCode = $order->get_shipping_postcode();
				$country = $order->get_shipping_country();

				$body['shippingAddress'] = array(
					'street'   => $anonymize ? $this->anonymizeValue( $street ) : $street,
					'town'     => $anonymize ? $this->anonymizeValue( $town ) : $town,
					'postCode' => $anonymize ? $this->anonymizeValue( $postCode ) : $postCode,
					'country'  => $anonymize ? $this->anonymizeValue( $country ) : $country,
				);
			}

			$body['timeCreated'] = $order->get_date_completed() !== null ? $order->get_date_completed()->__toString() : '';

			$response = wp_remote_post(
				API_URL . '/orders',
				array(
					'headers' => array(
						'Content-Type' => 'application/json',
						'x-api-key'    => $api_key,
					),
					'body'    => wp_json_encode( $body ),
				)
			);

			if ( is_wp_error( $response ) ) {
				// save last error to plugin options
				update_option( 'repetito_last_error', $response->get_error_message() );
			} else {
				$response_code = wp_remote_retrieve_response_code( $response );
				// Check if response code indicates an error (4xx or 5xx)
				if ( $response_code >= 400 ) {
					$response_body = wp_remote_retrieve_body( $response );
					$error_message = sprintf( 'HTTP %d: %s', $response_code, $response_body );
					update_option( 'repetito_last_error', $error_message );
				} else {
					// current time in ISO 8601 format
					update_option( 'repetito_last_error', null );
					update_option( 'repetito_last_order_sent', gmdate( 'c' ) );
				}
			}

			$this->integrationStatus();
		}
	}

	public function integrationStatus() {
		$settings = get_option( 'repetito-settings' );
		$api_key = isset($settings['api_key']) ? (string) $settings['api_key'] : '';

		if ( '' === $api_key ) {
			return;
		}

		$lastOrderSent = null;
		$lastError = null;


		$metadata = array();
		$allow_integration_status_metadata = isset($settings['allow_integration_status_metadata']) ? (bool) $settings['allow_integration_status_metadata'] : false;
		if ( $allow_integration_status_metadata ) {
			$settingsWithoutApiKey = $settings;
			$settingsWithoutApiKey['api_key'] = '********';
			$metadata = array(
				'phpVersion' => phpversion(),
				'wpVersion' => get_bloginfo('version'),
				'woocommerceVersion' => defined('WC_VERSION') ? WC_VERSION : 'unknown',
				'plugins' => array_map(function($plugin) {
					return $plugin['Version'];
				}, get_plugins()),
				'settings' => $settingsWithoutApiKey,
			);
			// find last order containing repetito fee
			$lastOrderSent = get_option( 'repetito_last_order_sent', null );
			$lastError = get_option( 'repetito_last_error', null );
		}

		$body = array(
			'platformType' => 'wordpress',
			'version' => VERSION,
			'lastOrderSent' => $lastOrderSent,
			'lastError' => $lastError,
			'metadata' => json_encode($metadata),
		);

		$response = wp_remote_post(
			API_URL . '/integration/status',
			array(
				'headers' => array(
					'Content-Type' => 'application/json',
					'x-api-key'    => $api_key,
				),
				'body'    => wp_json_encode( $body ),
			)
		);
	}
}