<?php

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

final class LVSW_Plugin {
	const OPTION_KEY          = 'lvsw_options_v1';
	const HASH_OPTION         = 'lvsw_js_hashes_v1';
	const PLUGINS_OPTION      = 'lvsw_plugins_list_v1';
	const ADMINS_OPTION       = 'lvsw_admins_list_v1';
	const LOG_OPTION          = 'lvsw_log_v1';
	const PRE_USER_OPTION     = 'lvsw_prev_pre_user_opts_v1';
	const STATS_OPTION        = 'lvsw_last_stats_v1';
	const BLOCKED_IPS_OPTION  = 'lvsw_blocked_ips_monthly_v1';
	const CRON_HOOK           = 'lvsw_cron_event';
	const MENU_SLUG           = 'lumiverse-security-watchdog-lite';
	const TEXT_DOMAIN         = 'lumiverse-security-watchdog-lite';

	const OLD_OPTION_KEY      = 'wp_sw_options_v1';
	const OLD_HASH_OPTION     = 'wp_sw_js_hashes_v1';
	const OLD_PLUGINS_OPTION  = 'wp_sw_plugins_list_v1';
	const OLD_ADMINS_OPTION   = 'wp_sw_admins_list_v1';
	const OLD_LOG_OPTION      = 'wp_sw_log_v1';
	const OLD_PRE_USER_OPT    = 'wp_sw_prev_pre_user_opts';
	const OLD_CRON_HOOK       = 'wp_sw_cron_event';

	const PRO_OPTION_KEY      = 'wp_swpro_options_v1';
	const PRO_HASH_OPTION     = 'wp_swpro_js_hashes_v1';
	const PRO_PLUGINS_OPTION  = 'wp_swpro_plugins_list_v1';
	const PRO_ADMINS_OPTION   = 'wp_swpro_admins_list_v1';
	const PRO_LOG_OPTION      = 'wp_swpro_log_v1';
	const PRO_PRE_USER_OPT    = 'wp_swpro_prev_pre_user_opts_v1';
	const PRO_STATS_OPTION    = 'wp_swpro_last_stats_v1';
	const PRO_BLOCKED_IPS_OPT = 'wp_swpro_blocked_ips_monthly_v1';
	const PRO_CRON_HOOK       = 'wp_swpro_cron_event';

	public static $allowed_intervals = array( 6, 12, 24 );
	public static $allowed_fast_days = array( 1, 7, 30 );

	private static $defaults = array(
		'enabled'                       => 0,
		'notify_email'                  => '',
		'scan_interval_hours'           => 24,
		'fast_mode_enabled'             => 1,
		'fast_mode_days'                => 7,
		'scan_js'                       => 1,
		'scan_plugins'                  => 1,
		'scan_themes'                   => 1,
		'scan_muplugins'                => 1,
		'scan_wpcontent_root'           => 1,
		'scan_uploads_php'              => 1,
		'uploads_exec_detection'        => 1,
		'scan_admins'                   => 1,
		'scan_core_recent_mtime'        => 1,
		'scan_core_suspicious'          => 1,
		'block_xmlrpc'                  => 0,
		'block_file_mods'               => 0,
		'disallow_file_mods'            => 0,
		'disable_deletion'              => 0,
		'secure_head_cleanup'           => 0,
		'hide_login_errors'             => 0,
		'limit_login_attempts'          => 0,
		'block_pingbacks'               => 0,
		'block_user_enum'               => 0,
		'block_comments'                => 0,
		'disable_application_passwords' => 0,
		'block_admin_password_reset'    => 0,
		'alert_users_can_register'      => 1,
		'fix_disable_user_registration' => 0,
		'admin_hygiene_checks'          => 1,
		'max_findings_per_group'        => 50,
		'uploads_scan_limit'            => 800,
		'signatures'                    => null,
		'last_run'                      => 0,
		'_v3_upgraded'                  => 0,
	);

	public static function init() {
		add_action( 'plugins_loaded', array( __CLASS__, 'load_textdomain' ) );
		add_action( 'init', array( __CLASS__, 'ensure_initialized' ), 20 );

		LVSW_Cron::init();
		LVSW_Hardening::init();
		LVSW_Admin::init();
	}

	public static function load_textdomain() {
		load_plugin_textdomain( self::TEXT_DOMAIN, false, dirname( plugin_basename( LVSW_FILE ) ) . '/languages' );
	}

	public static function get_defaults() {
		return self::$defaults;
	}

	public static function normalize_options( $opts ) {
		$opts = is_array( $opts ) ? $opts : array();
		$opts = wp_parse_args( $opts, self::$defaults );

		$opts['enabled']                       = ! empty( $opts['enabled'] ) ? 1 : 0;
		$opts['fast_mode_enabled']             = ! empty( $opts['fast_mode_enabled'] ) ? 1 : 0;
		$opts['scan_js']                       = ! empty( $opts['scan_js'] ) ? 1 : 0;
		$opts['scan_plugins']                  = ! empty( $opts['scan_plugins'] ) ? 1 : 0;
		$opts['scan_themes']                   = ! empty( $opts['scan_themes'] ) ? 1 : 0;
		$opts['scan_muplugins']                = ! empty( $opts['scan_muplugins'] ) ? 1 : 0;
		$opts['scan_wpcontent_root']           = ! empty( $opts['scan_wpcontent_root'] ) ? 1 : 0;
		$opts['scan_uploads_php']              = ! empty( $opts['scan_uploads_php'] ) ? 1 : 0;
		$opts['uploads_exec_detection']        = ! empty( $opts['uploads_exec_detection'] ) ? 1 : 0;
		$opts['scan_admins']                   = ! empty( $opts['scan_admins'] ) ? 1 : 0;
		$opts['scan_core_recent_mtime']        = ! empty( $opts['scan_core_recent_mtime'] ) ? 1 : 0;
		$opts['scan_core_suspicious']          = ! empty( $opts['scan_core_suspicious'] ) ? 1 : 0;
		$opts['block_xmlrpc']                  = ! empty( $opts['block_xmlrpc'] ) ? 1 : 0;
		$opts['block_file_mods']               = ! empty( $opts['block_file_mods'] ) ? 1 : 0;
		$opts['disallow_file_mods']            = ! empty( $opts['disallow_file_mods'] ) ? 1 : 0;
		$opts['disable_deletion']              = ! empty( $opts['disable_deletion'] ) ? 1 : 0;
		$opts['secure_head_cleanup']           = ! empty( $opts['secure_head_cleanup'] ) ? 1 : 0;
		$opts['hide_login_errors']             = ! empty( $opts['hide_login_errors'] ) ? 1 : 0;
		$opts['limit_login_attempts']          = ! empty( $opts['limit_login_attempts'] ) ? 1 : 0;
		$opts['block_pingbacks']               = ! empty( $opts['block_pingbacks'] ) ? 1 : 0;
		$opts['block_user_enum']               = ! empty( $opts['block_user_enum'] ) ? 1 : 0;
		$opts['block_comments']                = ! empty( $opts['block_comments'] ) ? 1 : 0;
		$opts['disable_application_passwords'] = ! empty( $opts['disable_application_passwords'] ) ? 1 : 0;
		$opts['block_admin_password_reset']    = ! empty( $opts['block_admin_password_reset'] ) ? 1 : 0;
		$opts['alert_users_can_register']      = ! empty( $opts['alert_users_can_register'] ) ? 1 : 0;
		$opts['fix_disable_user_registration'] = ! empty( $opts['fix_disable_user_registration'] ) ? 1 : 0;
		$opts['admin_hygiene_checks']          = ! empty( $opts['admin_hygiene_checks'] ) ? 1 : 0;
		$opts['_v3_upgraded']                  = ! empty( $opts['_v3_upgraded'] ) ? 1 : 0;

		$opts['notify_email'] = isset( $opts['notify_email'] ) ? sanitize_email( $opts['notify_email'] ) : '';

		$interval = isset( $opts['scan_interval_hours'] ) ? (int) $opts['scan_interval_hours'] : 24;
		if ( ! in_array( $interval, self::$allowed_intervals, true ) ) {
			$interval = 24;
		}
		$opts['scan_interval_hours'] = $interval;

		$days = isset( $opts['fast_mode_days'] ) ? (int) $opts['fast_mode_days'] : 7;
		if ( ! in_array( $days, self::$allowed_fast_days, true ) ) {
			$days = 7;
		}
		$opts['fast_mode_days'] = $days;

		$opts['max_findings_per_group'] = max( 10, (int) $opts['max_findings_per_group'] );
		$opts['uploads_scan_limit']     = max( 200, (int) $opts['uploads_scan_limit'] );
		$opts['last_run']               = ! empty( $opts['last_run'] ) ? (int) $opts['last_run'] : 0;

		if ( empty( $opts['signatures'] ) || ! is_array( $opts['signatures'] ) ) {
			$opts['signatures'] = LVSW_Scanner::default_signatures();
		}

		return $opts;
	}

	public static function get_opts() {
		return self::normalize_options( get_option( self::OPTION_KEY, array() ) );
	}

	public static function ensure_initialized() {
		self::maybe_migrate_from_legacy_and_pro();

		$opts = get_option( self::OPTION_KEY, null );
		if ( ! is_array( $opts ) ) {
			$opts = self::normalize_options( self::$defaults );
			update_option( self::OPTION_KEY, $opts );
		} else {
			$opts = self::normalize_options( $opts );
			if ( empty( $opts['_v3_upgraded'] ) ) {
				$opts['_v3_upgraded'] = 1;
				update_option( self::OPTION_KEY, $opts );
			} else {
				update_option( self::OPTION_KEY, $opts );
			}
		}

		LVSW_Cron::ensure_cron_scheduled();
	}

	private static function maybe_migrate_from_legacy_and_pro() {
		$current = get_option( self::OPTION_KEY, null );
		if ( is_array( $current ) && ! empty( $current ) ) {
			if ( empty( $current['_v3_upgraded'] ) ) {
				$current = self::normalize_options( self::map_legacy_free_options_to_v3( $current ) );
				$current['_v3_upgraded'] = 1;
				update_option( self::OPTION_KEY, $current );
			}
			wp_clear_scheduled_hook( self::OLD_CRON_HOOK );
			wp_clear_scheduled_hook( self::PRO_CRON_HOOK );
			return;
		}

		$source_opts = null;
		$source      = '';

		$free_legacy = get_option( self::OLD_OPTION_KEY, null );
		$pro_opts    = get_option( self::PRO_OPTION_KEY, null );

		if ( is_array( $pro_opts ) && ! empty( $pro_opts ) ) {
			$source_opts = self::map_pro_options_to_v3( $pro_opts );
			$source      = 'PRO';
		} elseif ( is_array( $free_legacy ) && ! empty( $free_legacy ) ) {
			$source_opts = self::map_old_keys_options_to_v3( $free_legacy );
			$source      = 'legacy';
		}

		if ( null === $source_opts ) {
			return;
		}

		update_option( self::OPTION_KEY, self::normalize_options( $source_opts ) );

		self::copy_option_if_missing( self::HASH_OPTION, self::PRO_HASH_OPTION, self::OLD_HASH_OPTION );
		self::copy_option_if_missing( self::PLUGINS_OPTION, self::PRO_PLUGINS_OPTION, self::OLD_PLUGINS_OPTION );
		self::copy_option_if_missing( self::ADMINS_OPTION, self::PRO_ADMINS_OPTION, self::OLD_ADMINS_OPTION );
		self::copy_option_if_missing( self::LOG_OPTION, self::PRO_LOG_OPTION, self::OLD_LOG_OPTION );
		self::copy_option_if_missing( self::PRE_USER_OPTION, self::PRO_PRE_USER_OPT, self::OLD_PRE_USER_OPT );
		self::copy_option_if_missing( self::STATS_OPTION, self::PRO_STATS_OPTION );
		self::copy_option_if_missing( self::BLOCKED_IPS_OPTION, self::PRO_BLOCKED_IPS_OPT );

		wp_clear_scheduled_hook( self::OLD_CRON_HOOK );
		wp_clear_scheduled_hook( self::PRO_CRON_HOOK );

		LVSW_Helpers::log_event( sprintf( 'Migrated settings and baselines from %s storage keys', $source ) );
	}

	private static function copy_option_if_missing( $target ) {
		$sources = func_get_args();
		array_shift( $sources );
		if ( null !== get_option( $target, null ) ) {
			return;
		}
		foreach ( $sources as $source ) {
			$value = get_option( $source, null );
			if ( null !== $value ) {
				update_option( $target, $value );
				return;
			}
		}
	}

	private static function map_legacy_free_options_to_v3( $opts ) {
		$opts                   = is_array( $opts ) ? $opts : array();
		$opts['scan_themes']    = isset( $opts['scan_themes'] ) ? $opts['scan_themes'] : 1;
		$opts['scan_muplugins'] = isset( $opts['scan_muplugins'] ) ? $opts['scan_muplugins'] : 1;
		$opts['scan_wpcontent_root']    = isset( $opts['scan_wpcontent_root'] ) ? $opts['scan_wpcontent_root'] : 1;
		$opts['scan_uploads_php']       = isset( $opts['scan_uploads_php'] ) ? $opts['scan_uploads_php'] : 1;
		$opts['uploads_exec_detection'] = isset( $opts['uploads_exec_detection'] ) ? $opts['uploads_exec_detection'] : 1;
		$opts['scan_core_recent_mtime'] = isset( $opts['scan_core_recent_mtime'] ) ? $opts['scan_core_recent_mtime'] : 1;
		$opts['scan_core_suspicious']   = isset( $opts['scan_core_suspicious'] ) ? $opts['scan_core_suspicious'] : 1;
		$opts['disable_deletion']       = isset( $opts['disable_deletion'] ) ? $opts['disable_deletion'] : 0;
		$opts['secure_head_cleanup']    = isset( $opts['secure_head_cleanup'] ) ? $opts['secure_head_cleanup'] : 0;
		$opts['hide_login_errors']      = isset( $opts['hide_login_errors'] ) ? $opts['hide_login_errors'] : 0;
		$opts['limit_login_attempts']   = isset( $opts['limit_login_attempts'] ) ? $opts['limit_login_attempts'] : 0;
		$opts['block_pingbacks']        = isset( $opts['block_pingbacks'] ) ? $opts['block_pingbacks'] : 0;
		$opts['block_user_enum']        = isset( $opts['block_user_enum'] ) ? $opts['block_user_enum'] : 0;
		$opts['disable_application_passwords'] = isset( $opts['disable_application_passwords'] ) ? $opts['disable_application_passwords'] : 0;
		$opts['alert_users_can_register']      = isset( $opts['alert_users_can_register'] ) ? $opts['alert_users_can_register'] : 1;
		$opts['fix_disable_user_registration'] = isset( $opts['fix_disable_user_registration'] ) ? $opts['fix_disable_user_registration'] : 0;
		$opts['admin_hygiene_checks']          = isset( $opts['admin_hygiene_checks'] ) ? $opts['admin_hygiene_checks'] : 1;
		$opts['disallow_file_mods']            = isset( $opts['disallow_file_mods'] ) ? $opts['disallow_file_mods'] : 0;
		$opts['fast_mode_enabled']             = isset( $opts['fast_mode_enabled'] ) ? $opts['fast_mode_enabled'] : 1;
		$opts['fast_mode_days']                = isset( $opts['fast_mode_days'] ) ? $opts['fast_mode_days'] : 7;
		$opts['max_findings_per_group']        = isset( $opts['max_findings_per_group'] ) ? $opts['max_findings_per_group'] : 50;
		$opts['uploads_scan_limit']            = isset( $opts['uploads_scan_limit'] ) ? $opts['uploads_scan_limit'] : 800;
		$opts['_v3_upgraded']                  = 1;
		return $opts;
	}

	private static function map_old_keys_options_to_v3( $opts ) {
		return self::map_legacy_free_options_to_v3( $opts );
	}

	private static function map_pro_options_to_v3( $opts ) {
		$mapped = array(
			'enabled'                       => ! empty( $opts['enabled'] ) ? 1 : 0,
			'notify_email'                  => isset( $opts['notify_email'] ) ? $opts['notify_email'] : '',
			'scan_interval_hours'           => isset( $opts['scan_interval_hours'] ) ? (int) $opts['scan_interval_hours'] : 24,
			'fast_mode_enabled'             => ! empty( $opts['fast_mode_enabled'] ) ? 1 : 0,
			'fast_mode_days'                => isset( $opts['fast_mode_days'] ) ? (int) $opts['fast_mode_days'] : 7,
			'scan_js'                       => ! empty( $opts['scan_js'] ) ? 1 : 0,
			'scan_plugins'                  => ! empty( $opts['scan_plugins'] ) ? 1 : 0,
			'scan_themes'                   => ! empty( $opts['scan_themes'] ) ? 1 : 0,
			'scan_muplugins'                => ! empty( $opts['scan_muplugins'] ) ? 1 : 0,
			'scan_wpcontent_root'           => ! empty( $opts['scan_wpcontent_root'] ) ? 1 : 0,
			'scan_uploads_php'              => ! empty( $opts['scan_uploads_php'] ) ? 1 : 0,
			'uploads_exec_detection'        => ! empty( $opts['uploads_exec_detection'] ) ? 1 : 0,
			'scan_admins'                   => ! empty( $opts['scan_admins'] ) ? 1 : 0,
			'scan_core_recent_mtime'        => ! empty( $opts['scan_core_recent_mtime'] ) ? 1 : 0,
			'scan_core_suspicious'          => ! empty( $opts['scan_core_suspicious'] ) ? 1 : 0,
			'block_xmlrpc'                  => ! empty( $opts['block_xmlrpc'] ) ? 1 : 0,
			'block_file_mods'               => ! empty( $opts['disallow_file_edit'] ) ? 1 : 0,
			'disallow_file_mods'            => ! empty( $opts['disallow_file_mods'] ) ? 1 : 0,
			'disable_deletion'              => ! empty( $opts['disable_deletion'] ) ? 1 : 0,
			'secure_head_cleanup'           => ! empty( $opts['secure_head_cleanup'] ) ? 1 : 0,
			'hide_login_errors'             => ! empty( $opts['hide_login_errors'] ) ? 1 : 0,
			'limit_login_attempts'          => ! empty( $opts['limit_login_attempts'] ) ? 1 : 0,
			'block_pingbacks'               => ! empty( $opts['block_pingbacks'] ) ? 1 : 0,
			'block_user_enum'               => ! empty( $opts['block_user_enum'] ) ? 1 : 0,
			'block_comments'                => ! empty( $opts['block_comments'] ) ? 1 : 0,
			'disable_application_passwords' => ! empty( $opts['disable_application_passwords'] ) ? 1 : 0,
			'block_admin_password_reset'    => ! empty( $opts['block_admin_password_reset'] ) ? 1 : 0,
			'alert_users_can_register'      => ! empty( $opts['alert_users_can_register'] ) ? 1 : 0,
			'fix_disable_user_registration' => ! empty( $opts['fix_disable_user_registration'] ) ? 1 : 0,
			'admin_hygiene_checks'          => ! empty( $opts['admin_hygiene_checks'] ) ? 1 : 0,
			'max_findings_per_group'        => isset( $opts['max_findings_per_group'] ) ? (int) $opts['max_findings_per_group'] : 50,
			'uploads_scan_limit'            => isset( $opts['uploads_scan_limit'] ) ? (int) $opts['uploads_scan_limit'] : 800,
			'signatures'                    => ! empty( $opts['signatures'] ) ? $opts['signatures'] : LVSW_Scanner::default_signatures(),
			'last_run'                      => ! empty( $opts['last_run'] ) ? (int) $opts['last_run'] : 0,
			'_v3_upgraded'                  => 1,
		);
		return $mapped;
	}

	public static function activate() {
		self::ensure_initialized();

		if ( null === get_option( self::PLUGINS_OPTION, null ) ) {
			LVSW_Scanner::initialize_baselines();
		} else {
			LVSW_Cron::reschedule_cron( true );
		}
	}

	public static function deactivate() {
		wp_clear_scheduled_hook( self::CRON_HOOK );
		wp_clear_scheduled_hook( self::OLD_CRON_HOOK );
		wp_clear_scheduled_hook( self::PRO_CRON_HOOK );
	}

	public static function uninstall() {
		$keys = array(
			self::OPTION_KEY,
			self::HASH_OPTION,
			self::PLUGINS_OPTION,
			self::ADMINS_OPTION,
			self::LOG_OPTION,
			self::PRE_USER_OPTION,
			self::STATS_OPTION,
			self::BLOCKED_IPS_OPTION,
			self::OLD_OPTION_KEY,
			self::OLD_HASH_OPTION,
			self::OLD_PLUGINS_OPTION,
			self::OLD_ADMINS_OPTION,
			self::OLD_LOG_OPTION,
			self::OLD_PRE_USER_OPT,
			self::PRO_OPTION_KEY,
			self::PRO_HASH_OPTION,
			self::PRO_PLUGINS_OPTION,
			self::PRO_ADMINS_OPTION,
			self::PRO_LOG_OPTION,
			self::PRO_PRE_USER_OPT,
			self::PRO_STATS_OPTION,
			self::PRO_BLOCKED_IPS_OPT,
		);
		foreach ( $keys as $key ) {
			delete_option( $key );
		}
		wp_clear_scheduled_hook( self::CRON_HOOK );
		wp_clear_scheduled_hook( self::OLD_CRON_HOOK );
		wp_clear_scheduled_hook( self::PRO_CRON_HOOK );
	}
}
