<?php
/**
 * Structured logging utility.
 *
 * @package ThemeREX\AutoDealer
 */

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Core;

/**
 * Logger with level-based filtering and structured context output.
 *
 * Log level is controlled by the TRX_AD_LOG_LEVEL constant.
 * Accepted values: 'error', 'warning', 'info'. Default: 'error'.
 */
class Logger {

	private const PREFIX = '[TRX Auto Dealer]';

	/**
	 * Numeric severity so we can compare levels.
	 *
	 * @var array<string, int>
	 */
	private const LEVELS = array(
		'error'   => 3,
		'warning' => 2,
		'info'    => 1,
	);

	/**
	 * Return the currently configured minimum log level.
	 *
	 * @return string
	 */
	private static function getMinLevel(): string {
		if ( defined( 'TRX_AD_LOG_LEVEL' ) && is_string( TRX_AD_LOG_LEVEL ) ) {
			$level = strtolower( TRX_AD_LOG_LEVEL );
			if ( isset( self::LEVELS[ $level ] ) ) {
				return $level;
			}
		}
		return 'error';
	}

	/**
	 * Determine whether a message at $level should be logged.
	 *
	 * @param string $level The level of the message being logged.
	 * @return bool
	 */
	private static function shouldLog( string $level ): bool {
		return self::LEVELS[ $level ] >= self::LEVELS[ self::getMinLevel() ];
	}

	/**
	 * Format a context array into a human-readable string.
	 *
	 * @param array<string, mixed> $context Arbitrary key/value pairs.
	 * @return string
	 */
	private static function formatContext( array $context ): string {
		if ( $context === array() ) {
			return '';
		}

		$parts = array();
		foreach ( $context as $key => $value ) {
			if ( is_array( $value ) || is_object( $value ) ) {
				$value = wp_json_encode( $value, JSON_UNESCAPED_SLASHES );
			} elseif ( is_bool( $value ) ) {
				$value = $value ? 'true' : 'false';
			} elseif ( is_null( $value ) ) {
				$value = 'null';
			}
			$parts[] = "{$key}={$value}";
		}

		return ' | ' . implode( ', ', $parts );
	}

	/**
	 * Write a log entry via error_log().
	 *
	 * @param string               $level   One of 'error', 'warning', 'info'.
	 * @param string               $message Human-readable message.
	 * @param array<string, mixed> $context Optional structured data.
	 * @return void
	 */
	private static function log( string $level, string $message, array $context = array() ): void {
		if ( ! self::shouldLog( $level ) ) {
			return;
		}

		$tag   = strtoupper( $level );
		$entry = sprintf( '%s [%s] %s%s', self::PREFIX, $tag, $message, self::formatContext( $context ) );

		// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
		error_log( $entry );
	}

	/**
	 * Log an error-level message.
	 *
	 * @param string               $message Human-readable message.
	 * @param array<string, mixed> $context Optional structured data.
	 * @return void
	 */
	public static function error( string $message, array $context = array() ): void {
		self::log( 'error', $message, $context );
	}

	/**
	 * Log a warning-level message.
	 *
	 * @param string               $message Human-readable message.
	 * @param array<string, mixed> $context Optional structured data.
	 * @return void
	 */
	public static function warning( string $message, array $context = array() ): void {
		self::log( 'warning', $message, $context );
	}

	/**
	 * Log an info-level message.
	 *
	 * @param string               $message Human-readable message.
	 * @param array<string, mixed> $context Optional structured data.
	 * @return void
	 */
	public static function info( string $message, array $context = array() ): void {
		self::log( 'info', $message, $context );
	}
}
