<?php
/**
 * Audit log. Custom table records every tool call: who, what, args, result,
 * timing. Used by the admin "Activity" tab and by the AI when it asks
 * "what did I just do."
 */

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

class PCD_PC_Audit {

	const TABLE_VERSION_OPT = 'pcd_pc_audit_db_version';
	const TABLE_VERSION     = '1';

	public static function init(): void {
		self::maybe_install_table();
	}

	private static function table_name(): string {
		global $wpdb;
		return $wpdb->prefix . 'pcd_pc_audit';
	}

	private static function maybe_install_table(): void {
		if ( get_option( self::TABLE_VERSION_OPT ) === self::TABLE_VERSION ) {
			return;
		}

		global $wpdb;
		$table   = self::table_name();
		$charset = $wpdb->get_charset_collate();

		$sql = "CREATE TABLE {$table} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			created_at DATETIME NOT NULL,
			user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
			tool VARCHAR(128) NOT NULL,
			args LONGTEXT NULL,
			result_status VARCHAR(32) NOT NULL DEFAULT 'ok',
			result LONGTEXT NULL,
			elapsed_ms INT UNSIGNED NOT NULL DEFAULT 0,
			snapshot_id BIGINT UNSIGNED NULL,
			PRIMARY KEY (id),
			KEY tool (tool),
			KEY created_at (created_at)
		) {$charset};";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $sql );
		update_option( self::TABLE_VERSION_OPT, self::TABLE_VERSION );
	}

	public static function record( string $tool, array $args, $result, int $elapsed_ms = 0 ): int {
		global $wpdb;

		$status = is_wp_error( $result ) ? 'error' : 'ok';
		if ( is_array( $result ) && ! empty( $result['requires_confirmation'] ) ) {
			$status = 'pending_confirm';
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- writing to the plugin's own audit table; no caching applicable.
		$wpdb->insert(
			self::table_name(),
			[
				'created_at'    => current_time( 'mysql', true ),
				'user_id'       => get_current_user_id(),
				'tool'          => $tool,
				'args'          => wp_json_encode( $args ),
				'result_status' => $status,
				'result'        => wp_json_encode( is_wp_error( $result ) ? [
					'code'    => $result->get_error_code(),
					'message' => $result->get_error_message(),
				] : $result ),
				'elapsed_ms'    => $elapsed_ms,
			]
		);

		return (int) $wpdb->insert_id;
	}

	public static function recent( int $limit = 50 ): array {
		global $wpdb;
		$limit = max( 1, min( 500, $limit ) );
		// phpcs:ignore WordPress.DB.PreparedSQL, WordPress.DB.DirectDatabaseQuery -- internal table name from $wpdb->prefix; limit uses prepare().
		return (array) $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM ' . self::table_name() . ' ORDER BY id DESC LIMIT %d', $limit ), ARRAY_A );
	}
}
