<?php

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

trait WPMR_Events_Log {

	function log_event( $event_type, $event_details, $user_id = null ) {
		$user_id = $user_id ?: get_current_user_id();

		// Retrieve the current event log
		$event_log = $this->get_setting( 'event_log' );
		if ( ! $event_log ) {
			$event_log = array();
		}

		// Purge events older than 100 days
		$threshold = time() - ( 100 * DAY_IN_SECONDS );
		$event_log = array_filter(
			$event_log,
			function ( $event ) use ( $threshold ) {
				return $event['timestamp'] >= $threshold;
			}
		);

		// Always limit to the last 10,000 entries
		if ( count( $event_log ) > 10000 ) {
			$event_log = array_slice( $event_log, -10000 );
		}

		$event = array(
			'event_type'    => $event_type,
			'event_details' => $event_details,
			'user_id'       => $user_id,
			'timestamp'     => time(),
		);

		if ( isset( $event_details['ip'] ) && filter_var( $event_details['ip'], FILTER_VALIDATE_IP ) ) {
			$hostname = gethostbyaddr( $event_details['ip'] );
			if ( $hostname && $hostname !== $event_details['ip'] ) {
				$event['event_details']['hostname'] = $hostname;
			}
		}

		// Add the new event
		$event_log[] = $event;
		// Save the updated log
		$this->update_setting( 'event_log', $event_log );
	}

	function log_automatic_update( $update_results ) {
		foreach ( $update_results as $result ) {
			$this->log_event(
				'automatic_update',
				array(
					'type'    => $result['type'] ?? 'unknown',
					'item'    => $result['item'] ?? 'unknown',
					'success' => $result['result'] ?? false,
				)
			);
		}
	}

	function log_update_event( $upgrader, $hook_extra ) {
		// Ensure the action is 'update'
		if ( ! isset( $hook_extra['action'], $hook_extra['type'] ) || $hook_extra['action'] !== 'update' ) {
			return;
		}

		$type = $hook_extra['type'];

		// Check for errors during the update process
		if ( ! empty( $upgrader->skin->errors ) ) {
			foreach ( $upgrader->skin->errors as $error ) {
				$this->log_event(
					$type . '_update_failed',
					array(
						'error'         => $error->get_error_message(),
						'type'          => $type,
						'extra_details' => $hook_extra,
					)
				);
			}
			return; // Exit early since update failed
		}

		// Log Core Update
		if ( $type === 'core' ) {
			$old_version = get_option( 'core_update_previous_version', null );
			$new_version = get_bloginfo( 'version' );
			$this->log_event(
				$type . '_updated',
				array(
					'old_version' => $old_version,
					'new_version' => $new_version,
					'extra'       => $hook_extra,
				)
			);
		}

		// Log Plugin Updates
		elseif ( $type === 'plugin' && isset( $hook_extra['plugins'] ) ) {
			foreach ( $hook_extra['plugins'] as $plugin ) {
				$plugin_path = WP_PLUGIN_DIR . '/' . $plugin;
				$old_version = file_exists( $plugin_path ) ? get_plugin_data( $plugin_path )['Version'] : 'Unknown';
				$new_version = $upgrader->skin->plugin_info['Version'] ?? 'Unknown';

				$this->log_event(
					$type . '_updated',
					array(
						'plugin'      => $plugin,
						'old_version' => $old_version,
						'new_version' => $new_version,
						'extra'       => $hook_extra,
					)
				);
			}
		}

		// Log Theme Updates
		elseif ( $type === 'theme' && isset( $hook_extra['themes'] ) ) {
			foreach ( $hook_extra['themes'] as $theme_slug ) {
				$theme       = wp_get_theme( $theme_slug );
				$old_version = $theme->get( 'Version' );
				$new_version = $upgrader->result['destination_name'] ?? 'Unknown';

				$this->log_event(
					$type . '_updated',
					array(
						'theme'       => $theme_slug,
						'old_version' => $old_version,
						'new_version' => $new_version,
						'extra'       => $hook_extra,
					)
				);
			}
		}

		// Log Translation Updates
		elseif ( $type === 'translation' ) {
			$this->log_event(
				$type . '_updated',
				array(
					'details' => 'WordPress translations updated successfully.',
					'extra'   => $hook_extra,
				)
			);
		}

		// Log Other Update Types
		else {
			$this->log_event(
				$type . '_updated',
				array(
					'type'    => $type,
					'details' => isset( $hook_extra ) ? json_encode( $hook_extra ) : 'Unknown update details.',
					'extra'   => $hook_extra,
				)
			);
		}
	}

	function log_plugin_toggle( $plugin, $network_wide ) {
		// Determine the event type based on the current hook
		$event_type = current_filter() === 'activated_plugin' ? 'plugin_activated' : 'plugin_deactivated';

		// Log the event
		$this->log_event(
			$event_type,
			array(
				'plugin'       => $plugin,
				'network_wide' => $network_wide,
			)
		);
	}

	function log_theme_activation( $new_theme ) {
		$this->log_event(
			'theme_activated',
			array(
				'theme' => $new_theme,
				'user'  => get_current_user_id(),
			)
		);
	}

	function log_plugin_deletion( $plugin ) {
		$this->log_event(
			'plugin_deleted',
			array(
				'plugin' => $plugin,
				'user'   => get_current_user_id(),
				'ip'     => $this->get_remote_ip(),
			)
		);
	}

	function log_theme_deletion( $theme ) {
		$this->log_event(
			'theme_deleted',
			array(
				'theme' => $theme,
				'user'  => get_current_user_id(),
				'ip'    => $this->get_remote_ip(),
			)
		);
	}

	function log_file_edit( $file, $type ) {
		$this->log_event(
			'file_edited',
			array(
				'file' => $file,
				'type' => $type,
				'user' => get_current_user_id(),
			)
		);
	}

	function log_file_upload( $file ) {
		$this->log_event(
			'file_uploaded',
			array(
				'file' => $file['file'],
				'user' => get_current_user_id(),
			)
		);
		return $file;
	}

	function log_add_attachment( $post_id ) {
		$file = get_attached_file( $post_id );
		$this->log_event(
			'attachment_added',
			array(
				'file'    => $file,
				'user_id' => get_current_user_id(),
			)
		);
	}

	function log_user_creation( $user_id ) {
		$user_info = get_userdata( $user_id );
		$this->log_event(
			'user_created',
			array(
				'user_id'  => $user_id,
				'username' => $user_info->user_login,
				'email'    => $user_info->user_email,
			)
		);
	}

	function log_user_update( $user_id, $old_user_data ) {
		$user_info = get_userdata( $user_id );
		$this->log_event(
			'user_updated',
			array(
				'user_id'  => $user_id,
				'username' => $user_info->user_login,
				'email'    => $user_info->user_email,
				'changes'  => array_diff_assoc( (array) $user_info->data, (array) $old_user_data->data ),
			)
		);
	}

	function log_user_role_change( $user_id, $new_role ) {
		$this->log_event(
			'user_role_changed',
			array(
				'user_id'  => $user_id,
				'new_role' => $new_role,
				'user'     => get_current_user_id(),
			)
		);
	}

	function log_password_reset_attempt() {
		$username = isset( $_POST['user_login'] ) ? sanitize_text_field( wp_unslash( $_POST['user_login'] ) ) : 'unknown'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This is a logging function that captures reset attempts, not processing form data
		$this->log_event(
			'password_reset_attempt',
			array(
				'username' => $username,
				'ip'       => $this->get_remote_ip(),
			)
		);
	}

	function log_user_deletion( $user_id ) {
		$user_info = get_userdata( $user_id );
		$this->log_event(
			'user_deleted',
			array(
				'user_id'  => $user_id,
				'username' => $user_info ? $user_info->user_login : 'unknown',
				'email'    => $user_info ? $user_info->user_email : 'unknown',
			)
		);
	}

	function log_add_user_to_blog( $user_id, $blog_id, $role ) {
		$this->log_event(
			'user_added_to_blog',
			array(
				'user_id' => $user_id,
				'blog_id' => $blog_id,
				'role'    => $role,
			)
		);
	}

	function log_failed_login( $username ) {
		// Determine the protocol
		$protocol = 'http';
		if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ) {
			$protocol = 'https';
		}

		// Retrieve the host
		$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : 'unknown_host'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- HTTP_HOST is sanitized below

		// Retrieve the request URI
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : 'unknown_uri'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- REQUEST_URI is sanitized below

		// Construct the full URL
		$full_url = $protocol . '://' . $host . $request_uri;

		// Log the failed login attempt with the full URL
		$event_details = array(
			'username' => $username,
			'ip'       => $this->get_remote_ip(),
			'url'      => $full_url,
		);

		// Assuming you have a function to log events
		$this->log_event( 'failed_login', $event_details );
	}

	function log_password_reset_request( $user_login ) {
		$this->log_event(
			'password_reset_requested',
			array(
				'username' => $user_login,
				'ip'       => $this->get_remote_ip(),
			)
		);
	}

	function log_successful_login( $user_login, $user ) {
		$this->log_event(
			'login_success',
			array(
				'username' => $user_login,
				'user_id'  => $user->ID,
				'ip'       => $this->get_remote_ip(),
			)
		);
	}

	function log_xmlrpc_publish_post( $post_id ) {
		$post = get_post( $post_id );
		$this->log_event(
			'xmlrpc_post_published',
			array(
				'post_id'    => $post_id,
				'post_title' => $post->post_title,
				'user_id'    => $post->post_author,
				'ip'         => $this->get_remote_ip(),
			)
		);
	}

	function log_malware_scan_start( $settings ) {
		$this->log_event(
			'malcure_scan_initiated',
			array(
				'settings' => $settings,
				'ip'       => $this->get_remote_ip(),
			)
		);
	}

	function log_malware_scan_complete() {
		$this->log_event(
			'malcure_scan_completed',
			array(
				'ip' => $this->get_remote_ip(),
			)
		);
	}

	function format_event_details( $event_details ) {
		// Handle array or object details
		if ( is_array( $event_details ) || is_object( $event_details ) ) {
			return wp_json_encode( $event_details, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
		}

		// Handle string or other scalar values
		return $event_details;
	}

	function get_user_display_name( $user_id ) {
		// If no user ID is provided, return "System"
		if ( ! $user_id ) {
			return 'SYSTEM';
		}

		$user = get_userdata( $user_id );
		return $user ? $user->display_name : 'Unknown User';
	}
}
