<?php
/**
 * Activity Guard – Real Time Notifier to Slack Rest Route.
 *
 * This class is used to response and all rest route works.
 *
 * @package WPNTS\Inc
 */

namespace WPNTS\Inc;

use WPNTS\Inc\wpnts_nts_fs; // phpcs:ignore
use WPNTS\Inc\Activate; // phpcs:ignore
use WPNTS\Inc\Deactivate; // phpcs:ignore
use WPNTS\Inc\Database\DB; // phpcs:ignore
use WPNTS\Inc\SlackAttachment; // phpcs:ignore
use WPNTS\Inc\SlackChannelRouter; // phpcs:ignore

defined('ABSPATH') || die('Hey, what are you doing here? You silly human!');
/**
 * Update used to rest route created.
 *
 * @since 1.0.0
 */
class Theme {

	/**
	 * Construct method.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		$wpnts_db_instance = new DB();
		$schedules_int = get_option( 'wpntswebhook_theme_settings');
		$schedules_interval = json_decode($schedules_int);

		$themeactivation = $schedules_interval->themeactivation ?? 'false';
		$themedeletion = $schedules_interval->themedeletion ?? 'false';
		$themeinstalled = $schedules_interval->themeinstalled ?? 'false';
		$themeupdate = $schedules_interval->themeupdate ?? 'false';
		$generalsettingspage = $schedules_interval->generalsettingspage ?? 'false';
		$theme_files_edited = $schedules_interval->theme_files_edited ?? 'false';
		$template_change_tracking = $schedules_interval->template_change_tracking ?? 'false';

		/**
		 * Hook into theme activation for monitoring only – does NOT modify or interfere with theme changes.
		 * This is strictly for logging and sending notifications to admin when a user activates a theme.
		 */
		if ( true === $themeactivation ) {
			add_action('switch_theme', [ $this, 'wpnts_theme_activated' ], 10, 2);
		}

		 // Hook into the theme update process who updated the theme.
		if ( true === $themeinstalled ) {
			add_action('admin_init', [ $this, 'check_newly_installed_themes' ]);
		}

		// Hook into theme deletion.
		if ( true === $themedeletion ) {
			add_action('delete_theme', [ $this, 'wpnts_theme_deleted' ]);
		}

		// Hook into theme updated.
		if ( true === $themeupdate ) {
			add_action('upgrader_process_complete', [ $this, 'wpnts_theme_updated' ], 10, 2);
		}

		 // Hook into option updates Settings => General.
		if ( true === $generalsettingspage ) {
			add_action('update_option', [ $this, 'wpnts_option_updated' ], 10, 3);
		}

		 // Schedule the file monitoring cron job.
		if ( true === $theme_files_edited ) {
			add_action('admin_init', [ $this, 'monitor_theme_files' ]);
		}

		// Theme template hook.
		if ( true === $template_change_tracking ) {
			add_action('updated_post_meta', [ $this, 'wpnts_detect_template_change' ], 10, 4);
			add_action('added_post_meta', [ $this, 'wpnts_detect_template_change' ], 10, 4);
		}
	}


	/**
	 * Detects changes to the page template and sends a notification.
	 *
	 * @param int    $meta_id    The meta ID.
	 * @param int    $post_id    The post ID.
	 * @param string $meta_key   The meta key.
	 * @param mixed  $meta_value The meta value.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function wpnts_detect_template_change( $meta_id, $post_id, $meta_key, $meta_value ) {
		// Only track page template changes.
		if ( $meta_key !== '_wp_page_template' ) {
			return;
		}

		// Get post information.
		$post = get_post($post_id);

		// Only proceed if this is a page.
		if ( ! $post || $post->post_type !== 'page' ) {
			return;
		}

		// Get the previous template.
		$old_template = get_post_meta($post_id, '_wpnts_last_template', true);

		// Skip if this is the first template being set or if no change.
		if ( empty($old_template) || $old_template === $meta_value ) {
			// Store current template for future comparison.
			update_post_meta($post_id, '_wpnts_last_template', $meta_value);
			return;
		}

		// Get current user.
		$current_user = wp_get_current_user();
		$changed_by = $current_user->display_name;

		// Get page title.
		$page_title = $post->post_title;

		// Format the template names to be more readable.
		$old_template_name = $old_template === 'default' ? 'Default Template' : basename($old_template, '.php');
		$new_template_name = $meta_value === 'default' ? 'Default Template' : basename($meta_value, '.php');

		// Create a nice template name format.
		$old_template_name = ucwords(str_replace([ '-', '_' ], ' ', $old_template_name));
		$new_template_name = ucwords(str_replace([ '-', '_' ], ' ', $new_template_name));

		// Initialize the SlackAttachment handler.
		$attachmentHandler = new SlackAttachment();
		$site_url = $attachmentHandler->getSiteURLAddOption();
		$page_edit_url = admin_url('post.php?post=' . $post_id . '&action=edit');

		// Default template for page template change alert
		$default_template = ":page_facing_up: Page template changed for '{page_title}' by {user_name}. Changed from '{old_template}' to '{new_template}'. {site_url}";
		
		// Template data for placeholders
		$template_data = [
			'page_title' => $page_title,
			'user_name' => $changed_by,
			'old_template' => $old_template_name,
			'new_template' => $new_template_name,
		];

		// Send templated notification with custom message support
		$attachmentHandler->send_templated_notification( 
			$this->get_webhook_url(), 
			$default_template,
			$template_data,
			'Medium', 
			'Template Changed',
			'wpntswebhook_theme_settings', // Settings option name
			'template_change_tracking_message', // Template key
			$changed_by
		);

		// Log to database.
		$log_message = "Page template for <b>'{$page_title}'</b> has been changed by 👉 <b>{$changed_by}</b> <br>From: <b>{$old_template_name}</b> <br>To: <b>{$new_template_name}</b> <br>Page URL: <a href='{$page_edit_url}' target='_blank'>{$page_edit_url}</a> <br>{$site_url}";
		$severity = 'Medium';
		$event_type = 'Template Changed';
		$time = current_time('mysql');
		$ip = $attachmentHandler->get_user_ip();
		$attachmentHandler->log_activity_to_db($severity, $time, $ip, $changed_by, $event_type, $log_message);

		// Update the stored template reference.
		update_post_meta($post_id, '_wpnts_last_template', $meta_value);
	}




	/**
	 * Handles theme activation and sends a notification when a theme is activated.
	 * This function is called only when a user manually activates a theme.
	 * It does NOT activate themes programmatically or alter user actions.
	 *
	 * @param string $new_name The name of the activated theme.
	 * @param object $new_theme The theme object of the newly activated theme.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function wpnts_theme_activated( $new_name, $new_theme ) {
		$activated_by = wp_get_current_user()->display_name;

		// Get the site URL, including child site for multisite.
		$attachmentHandler = new SlackAttachment();
		$site_url = $attachmentHandler->getSiteURLAddOption();

		// Default template for theme activation alert
		$default_template = ":art: Theme '{theme_name}' activated by {user_name}. {site_url}";
		
		// Template data for placeholders
		$template_data = [
			'theme_name' => $new_name,
			'user_name' => $activated_by,
		];

		// Send templated notification with custom message support
		$attachmentHandler->send_templated_notification( 
			$this->get_webhook_url(), 
			$default_template,
			$template_data,
			'High', 
			'Theme Activation',
			'wpntswebhook_theme_settings', // Settings option name
			'themeactivation_message', // Template key
			$activated_by
		);

		$log_message = "Theme <b>'$new_name'</b> has been activated by 👉 <b>$activated_by.</b>  <br> $site_url";
		$severity = 'High';
		$event_type = 'Activated';
		$time = current_time( 'mysql' );
		$ip = $attachmentHandler->get_user_ip();
		$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $activated_by, $event_type, $log_message  );
	}

	/**
	 * Theme Instelled.
	 */
	public function check_newly_installed_themes() {
		$previously_installed_themes = get_option('previously_installed_themes', []);
		$current_installed_themes = wp_get_themes();

		// Get the site URL, including child site for multisite.
		$attachmentHandler = new SlackAttachment();
		$site_url = $attachmentHandler->getSiteURLAddOption();

		if ( empty($previously_installed_themes) ) {
			// First time the function is called.
			$message = 'Your site has the following themes installed: (🌐 Site: ' . $site_url . ')';
			foreach ( $current_installed_themes as $theme_slug => $theme_info ) {
				$message .= "\n- {$theme_info->get('Name')}";
			}
			$message .= "\nI will send a notification if any new themes are installed.";

			// Send an informational message.
			$this->wpnts_notify_slack($message, ':information_source:');
		} else {
			// Detect newly installed themes.
			$newly_installed_themes = array_diff_key($current_installed_themes, $previously_installed_themes);

			if ( ! empty($newly_installed_themes) ) {
				foreach ( $newly_installed_themes as $theme_slug => $theme_info ) {
					$installed_by = wp_get_current_user()->display_name;
					$theme_name = $theme_info->get('Name');
					
					// Default template for theme installation alert
					$default_template = ":art: New theme '{theme_name}' installed by {user_name}. {site_url}";
					
					// Template data for placeholders
					$template_data = [
						'theme_name' => $theme_name,
						'user_name' => $installed_by,
					];

					// Send templated notification with custom message support
					$attachmentHandler->send_templated_notification( 
						$this->get_webhook_url(), 
						$default_template,
						$template_data,
						'High', 
						'Theme Installation',
						'wpntswebhook_theme_settings', // Settings option name
						'themeinstalled_message', // Template key
						$installed_by
					);
					
					$log_message = "New theme <b>'" . $theme_name . "'</b> has been installed by 👉 <b>$installed_by.</b>  <br> $site_url";
					$severity = 'High';
					$event_type = 'Activated';
					$time = current_time( 'mysql' );

					$ip = $attachmentHandler->get_user_ip();
					$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $installed_by, $event_type, $log_message  );

				}
			}
		}

		// Update the stored list of installed themes.
		update_option('previously_installed_themes', $current_installed_themes);
	}



	/**
	 * Handles theme deletion and sends a notification when a theme is deleted.
	 *
	 * @param string $stylesheet The stylesheet (theme) name that was deleted.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function wpnts_theme_deleted( $stylesheet ) {
		$deleted_by = wp_get_current_user()->display_name;

		// Get the site URL, including child site for multisite.
		$attachmentHandler = new SlackAttachment();
		$site_url = $attachmentHandler->getSiteURLAddOption();

		// Default template for theme deletion alert
		$default_template = ":wastebasket: Theme '{theme_name}' deleted by {user_name}. {site_url}";
		
		// Template data for placeholders
		$template_data = [
			'theme_name' => $stylesheet,
			'user_name' => $deleted_by,
		];

		// Send templated notification with custom message support
		$attachmentHandler->send_templated_notification( 
			$this->get_webhook_url(), 
			$default_template,
			$template_data,
			'High', 
			'Theme Deletion',
			'wpntswebhook_theme_settings', // Settings option name
			'themedeletion_message', // Template key
			$deleted_by
		);

		// Get the stored list of installed themes.
		$previously_installed_themes = get_option('previously_installed_themes', []);

		// Remove the deleted theme from the list.
		unset($previously_installed_themes[ $stylesheet ]);

		// Update the stored list of installed themes without the deleted theme.
		update_option('previously_installed_themes', $previously_installed_themes);

		$log_message = "Theme <b>'$stylesheet'</b> has been deleted by 👉 <b>$deleted_by.</b>  <br> $site_url";
		$severity = 'High';
		$event_type = 'Activated';
		$time = current_time( 'mysql' );
		$ip = $attachmentHandler->get_user_ip();
		$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $deleted_by, $event_type, $log_message  );
	}


	/**
	 * Handles theme updates and sends a notification when a theme is updated.
	 *
	 * @param object $upgrader_object The upgrader object handling the update.
	 * @param array  $options         Options related to the update action, including themes and action type.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function wpnts_theme_updated( $upgrader_object, $options ) {
		$updated_by = wp_get_current_user()->display_name;

		// Get the site URL, including child site for multisite.
		$attachmentHandler = new SlackAttachment();
		$site_url = $attachmentHandler->getSiteURLAddOption();

		if ( $options['action'] === 'update' && $options['type'] === 'theme' ) {
			foreach ( $options['themes'] as $theme ) {
				$theme_data = wp_get_theme($theme);
				$theme_name = $theme_data->get('Name');
				
				// Default template for theme update alert
				$default_template = ":art: Theme '{theme_name}' has been updated by {user_name}. {site_url}";
				
				// Template data for placeholders
				$template_data = [
					'theme_name' => $theme_name,
					'user_name' => $updated_by,
				];

				// Send templated notification with custom message support
				$attachmentHandler->send_templated_notification( 
					$this->get_webhook_url(), 
					$default_template,
					$template_data,
					'High', 
					'Theme Update',
					'wpntswebhook_theme_settings', // Settings option name
					'themeupdate_message', // Template key
					$updated_by
				);

				$log_message = "Theme <b>'$theme_name'</b> has been updated  by 👉 <b>$updated_by</b>.  <br> $site_url";
				$severity = 'High';
				$event_type = 'Updated';
				$time = current_time( 'mysql' );
				$ip = $attachmentHandler->get_user_ip();
				$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $updated_by, $event_type, $log_message  );

			}
		}
	}


	/**
	 * Handles the update of specific WordPress options and sends a notification.
	 *
	 * @param string $option   The name of the updated option.
	 * @param mixed  $old_value The previous value of the option.
	 * @param mixed  $value     The new value of the option.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function wpnts_option_updated( $option, $old_value, $value ) {
		$tracked_options = [ 'blogname', 'blogdescription', 'siteurl', 'home', 'admin_email', 'WPLANG', 'timezone_string', 'date_format', 'time_format' ];

		if ( in_array($option, $tracked_options) ) {
			$updated_by = wp_get_current_user()->display_name;

			// Get the site URL, including child site for multisite.
			$attachmentHandler = new SlackAttachment();
			$site_url = $attachmentHandler->getSiteURLAddOption();

			// Default template for general settings change alert
			$default_template = ":gear: Option '{option_name}' updated by {user_name}. Old Value: '{old_value}', New Value: '{new_value}'. {site_url}";
			
			// Template data for placeholders
			$template_data = [
				'option_name' => $option,
				'user_name' => $updated_by,
				'old_value' => $old_value,
				'new_value' => $value,
			];

			// Send templated notification with custom message support
			$attachmentHandler->send_templated_notification( 
				$this->get_webhook_url(), 
				$default_template,
				$template_data,
				'High', 
				'General Settings',
				'wpntswebhook_theme_settings', // Settings option name
				'generalsettingspage_message', // Template key
				$updated_by
			);

			$log_message = "General Settings data <b>'$option'</b> has been updated by 👉 <b>$updated_by.</b><br><b>Old Value:</b> $old_value,<br> <b>New Value</b>: $value <br>  $site_url";

			$severity = 'High';
			$event_type = 'General';
			$time = current_time( 'mysql' );
			$ip = $attachmentHandler->get_user_ip();
			$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $updated_by, $event_type, $log_message  );

		}
	}


	/**
	 * Handles the theme file and monitor when its edit and sends a notification.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function monitor_theme_files() {
		$filename    = isset( $_POST['file'] ) ? sanitize_text_field( wp_unslash( $_POST['file'] ) ) : false;
		$action  = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : false;
		$referer = isset( $_POST['_wp_http_referer'] ) ? sanitize_text_field( wp_unslash( $_POST['_wp_http_referer'] ) ) : false;
		$nonce   = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : false;

		$referer = remove_query_arg( array( 'file', 'theme', 'plugin' ), $referer );
		$referer = basename( $referer, '.php' );

		if ( 'edit-theme-plugin-file' === $action ) {
			if ( 'theme-editor' === $referer ) {
				$themename = isset( $_POST['theme'] ) ? sanitize_text_field( wp_unslash( $_POST['theme'] ) ) : false;
				if ( ! wp_verify_nonce( $nonce, 'edit-theme_' . $themename . '_' . $filename ) ) {
					return;
				}
				$message = "Details: $themename / $filename";

				$this->log_theme_file_edit($message);
			}
		}
	}

	/**
	 * Log the theme file edit action and send Slack notification.
	 *
	 * @param string $message The message to log and send to Slack.
	 */
	private function log_theme_file_edit( $message ) {
		$attachmentHandler = new SlackAttachment();
		$current_user = wp_get_current_user();
		$user_name = $current_user->display_name ?: 'System';
		
		// Parse the message to extract theme name and file name
		$parts = explode(' / ', str_replace('Details: ', '', $message));
		$theme_name = $parts[0] ?? 'Unknown Theme';
		$file_name = $parts[1] ?? 'Unknown File';
		
		// Default template for theme file edit alert
		$default_template = ":pencil2: Theme file edited: {file_name} in theme {theme_name} by {user_name}. {site_url}";
		
		// Template data for placeholders
		$template_data = [
			'file_name' => $file_name,
			'theme_name' => $theme_name,
			'user_name' => $user_name,
		];

		// Send templated notification with custom message support
		$attachmentHandler->send_templated_notification( 
			$this->get_webhook_url(), 
			$default_template,
			$template_data,
			'High', 
			'File Modification',
			'wpntswebhook_theme_settings', // Settings option name
			'theme_files_edited_message', // Template key
			$user_name
		);
		
		$site_url = $attachmentHandler->getSiteURLAddOption();
		$log_message = "Theme file changes detected: $site_url<br>$message";
		$severity = 'High';
		$event_type = 'File Modification';
		$time = current_time( 'mysql' );
		$ip = $attachmentHandler->get_user_ip();
		$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $user_name, $event_type, $log_message );
	}



	/**
	 * Get webhook URL from theme settings
	 *
	 * @return string
	 */
	private function get_webhook_url() {
		$schedules_int = get_option('wpntswebhook_theme_settings');
		$schedules_interval = json_decode($schedules_int);
		return $schedules_interval->webhook ?? '';
	}

	/**
	 * Sends a notification message to a configured Slack webhook using reusable function.
	 *
	 * This function formats a message with an optional emoji and sends it to the Slack webhook URL.
	 * specified in the plugin's comment settings.
	 *
	 * @param string $message The message to send to Slack.
	 * @param string $emoji   An optional emoji to prepend to the message.
	 * @return void
	 */
	private function wpnts_notify_slack( $message, $emoji = '' ) {
		$formatted_message = $emoji . ' ' . $message;
		
		// Use SlackChannelRouter for channel and user tag support
		SlackChannelRouter::send_notification_with_routing(
			'wpntswebhook_theme_settings',
			$formatted_message
		);
	}
}
