<?php
/**
 * Logging service using WooCommerce Logger.
 *
 * @package Carticy\CheckoutShield\Services
 */

declare(strict_types=1);

namespace Carticy\CheckoutShield\Services;

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

/**
 * Handles all logging for the plugin using WooCommerce Logger.
 */
final class LoggingService {

	/**
	 * Log source identifier.
	 */
	private const SOURCE = 'carticy-checkout-shield';

	/**
	 * Whitelist service for proxy-aware IP detection.
	 *
	 * @var WhitelistService|null
	 */
	private ?WhitelistService $whitelist_service = null;

	/**
	 * Constructor.
	 *
	 * @param WhitelistService|null $whitelist_service Optional whitelist service for IP detection.
	 */
	public function __construct( ?WhitelistService $whitelist_service = null ) {
		$this->whitelist_service = $whitelist_service;
	}

	/**
	 * Log a detection event.
	 *
	 * @param string $origin          The request origin (store_api, classic_ajax).
	 * @param bool   $validation_passed Whether validation passed.
	 * @param array  $context         Additional context data.
	 */
	public function log_detection( string $origin, bool $validation_passed, array $context = array() ): void {
		$logger = $this->get_logger();
		if ( ! $logger ) {
			return;
		}

		$status  = $validation_passed ? 'passed' : 'blocked';
		$message = sprintf(
			'Checkout request %s. Origin: %s, IP: %s',
			$status,
			$origin,
			$this->get_client_ip_for_log()
		);

		$log_context = array_merge(
			array(
				'source'     => self::SOURCE,
				'origin'     => $origin,
				'status'     => $status,
				'ip'         => $this->get_client_ip_for_log(),
				'user_agent' => $this->get_user_agent(),
				'timestamp'  => time(),
			),
			$context
		);

		if ( $validation_passed ) {
			$logger->info( $message, $log_context );
		} else {
			$logger->warning( $message, $log_context );
		}
	}

	/**
	 * Log an info message.
	 *
	 * @param string $message The message to log.
	 * @param array  $context Additional context.
	 */
	public function info( string $message, array $context = array() ): void {
		$logger = $this->get_logger();
		if ( $logger ) {
			$logger->info( $message, array_merge( array( 'source' => self::SOURCE ), $context ) );
		}
	}

	/**
	 * Log a warning message.
	 *
	 * @param string $message The message to log.
	 * @param array  $context Additional context.
	 */
	public function warning( string $message, array $context = array() ): void {
		$logger = $this->get_logger();
		if ( $logger ) {
			$logger->warning( $message, array_merge( array( 'source' => self::SOURCE ), $context ) );
		}
	}

	/**
	 * Log an error message.
	 *
	 * @param string $message The message to log.
	 * @param array  $context Additional context.
	 */
	public function error( string $message, array $context = array() ): void {
		$logger = $this->get_logger();
		if ( $logger ) {
			$logger->error( $message, array_merge( array( 'source' => self::SOURCE ), $context ) );
		}
	}

	/**
	 * Get WooCommerce logger instance.
	 *
	 * @return \WC_Logger_Interface|null
	 */
	private function get_logger(): ?\WC_Logger_Interface {
		if ( function_exists( 'wc_get_logger' ) ) {
			return wc_get_logger();
		}
		return null;
	}

	/**
	 * Get client IP for logging (truncated for privacy).
	 *
	 * @return string
	 */
	private function get_client_ip_for_log(): string {
		// Use proxy-aware IP detection if whitelist service is available.
		if ( $this->whitelist_service ) {
			$ip = $this->whitelist_service->get_client_ip();
		} else {
			$ip = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ?? '' ) );
		}

		// Truncate last octet for privacy (IPv4).
		if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
			$parts    = explode( '.', $ip );
			$parts[3] = 'xxx';
			return implode( '.', $parts );
		}

		// For IPv6, truncate more aggressively.
		if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
			$parts = explode( ':', $ip );
			return implode( ':', array_slice( $parts, 0, 4 ) ) . '::xxxx';
		}

		return $ip;
	}

	/**
	 * Get user agent for logging.
	 *
	 * @return string
	 */
	private function get_user_agent(): string {
		$ua = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) );
		// Truncate for log readability.
		return mb_substr( $ua, 0, 100 );
	}
}
