<?php
/**
 * Plugin logger.
 *
 * @package NaveenCodesImageOptimizer
 */

namespace NaveenCodesImageOptimizer;

defined( 'ABSPATH' ) || exit;

/**
 * Stores a capped set of structured log rows in wp_options.
 */
class Logger {

	/**
	 * Option key.
	 */
	const OPTION_KEY = 'naveencodes_logs';

	/**
	 * Maximum number of log items retained.
	 */
	const MAX_ITEMS = 200;

	/**
	 * Persist a log row.
	 *
	 * @param string $level   Log level.
	 * @param string $message Human-readable message.
	 * @param array  $context Optional context.
	 * @return void
	 */
	public function log( $level, $message, $context = array() ) {
		$logs = get_option( self::OPTION_KEY, array() );

		if ( ! is_array( $logs ) ) {
			$logs = array();
		}

		$logs[] = array(
			'timestamp' => current_time( 'mysql' ),
			'level'     => sanitize_key( $level ),
			'message'   => sanitize_text_field( $message ),
			'context'   => $this->sanitize_context( $context ),
		);

		if ( count( $logs ) > self::MAX_ITEMS ) {
			$logs = array_slice( $logs, -1 * self::MAX_ITEMS );
		}

		update_option( self::OPTION_KEY, $logs, false );
	}

	/**
	 * Return logs ordered from newest to oldest.
	 *
	 * @param int $limit Items to return.
	 * @return array
	 */
	public function get_logs( $limit = 100 ) {
		$logs = get_option( self::OPTION_KEY, array() );

		if ( ! is_array( $logs ) ) {
			return array();
		}

		$logs = array_reverse( $logs );

		return array_slice( $logs, 0, max( 1, absint( $limit ) ) );
	}

	/**
	 * Clear all logs.
	 *
	 * @return void
	 */
	public function clear() {
		delete_option( self::OPTION_KEY );
	}

	/**
	 * Normalize context data for storage.
	 *
	 * @param array $context Raw context.
	 * @return array
	 */
	protected function sanitize_context( $context ) {
		$clean = array();

		foreach ( (array) $context as $key => $value ) {
			$key = sanitize_key( (string) $key );

			if ( is_scalar( $value ) || null === $value ) {
				$clean[ $key ] = sanitize_text_field( (string) $value );
				continue;
			}

			$encoded = wp_json_encode( $value );
			$clean[ $key ] = is_string( $encoded ) ? sanitize_textarea_field( $encoded ) : '';
		}

		return $clean;
	}
}
