<?php
/**
 * Cleanup audit log.
 *
 * @package DatabaseCleanup
 */

namespace DatabaseCleanup\Includes;

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

class Cleanup_Logger {

	public const OPTION_KEY  = 'wpps_dc_cleanup_log';
	public const MAX_ENTRIES = 50;

	/**
	 * @param array<string, mixed> $entry
	 */
	public static function append( array $entry ): void {
		$log = self::get_all_raw();

		$entry['id'] = wp_generate_uuid4();

		array_unshift( $log, $entry );
		$log = array_slice( $log, 0, self::MAX_ENTRIES );

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

	/**
	 * @return list<array<string, mixed>>
	 */
	public static function get_all(): array {
		$log = self::get_all_raw();

		foreach ( $log as $index => &$entry ) {
			if ( ! is_array( $entry ) ) {
				continue;
			}
			if ( empty( $entry['id'] ) ) {
				$entry['id'] = 'legacy_' . (int) ( $entry['timestamp'] ?? 0 ) . '_' . $index;
			}
		}
		unset( $entry );

		return $log;
	}

	/**
	 * @return list<array<string, mixed>>
	 */
	private static function get_all_raw(): array {
		$log = get_option( self::OPTION_KEY, [] );

		return is_array( $log ) ? $log : [];
	}

	/**
	 * @return list<array<string, mixed>>
	 */
	public static function get_recent( int $limit = 10 ): array {
		return array_slice( self::get_all(), 0, max( 1, $limit ) );
	}

	public static function get_by_id( string $id ): ?array {
		foreach ( self::get_all() as $entry ) {
			if ( (string) ( $entry['id'] ?? '' ) === $id ) {
				return $entry;
			}
		}

		return null;
	}

	/**
	 * @param list<string> $ids
	 */
	public static function delete_by_ids( array $ids ): int {
		$ids = array_values(
			array_filter(
				array_map( 'sanitize_text_field', $ids ),
				static fn( string $id ): bool => $id !== ''
			)
		);

		if ( $ids === [] ) {
			return 0;
		}

		$log     = self::get_all();
		$before  = count( $log );
		$removed = 0;
		$keep    = [];

		foreach ( $log as $entry ) {
			if ( in_array( (string) ( $entry['id'] ?? '' ), $ids, true ) ) {
				++$removed;
				continue;
			}
			$keep[] = $entry;
		}

		if ( $removed > 0 ) {
			update_option( self::OPTION_KEY, $keep, false );
		}

		return $removed;
	}

	public static function clear(): void {
		delete_option( self::OPTION_KEY );
	}
}
