<?php

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

final class LVSW_Hardening {
	public static function init() {
		add_action( 'plugins_loaded', array( __CLASS__, 'maybe_block_file_editing' ), 1 );
		add_action( 'plugins_loaded', array( __CLASS__, 'maybe_disallow_file_mods' ), 1 );

		add_action( 'init', array( __CLASS__, 'maybe_block_xmlrpc' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_secure_head_cleanup' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_hide_login_errors' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_limit_login_attempts' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_block_pingbacks' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_block_user_enumeration' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_block_comments' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_disable_application_passwords' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_block_admin_password_reset' ), 1 );
		add_action( 'init', array( __CLASS__, 'maybe_fix_users_can_register' ), 5 );

		add_action( 'admin_init', array( __CLASS__, 'maybe_disable_theme_plugin_deletion' ), 1 );
		add_filter( 'map_meta_cap', array( __CLASS__, 'filter_caps_disable_deletion' ), 10, 4 );
		add_filter( 'plugin_action_links', array( __CLASS__, 'filter_plugin_action_links_no_delete' ), 10, 4 );
		add_filter( 'theme_action_links', array( __CLASS__, 'filter_theme_action_links_no_delete' ), 10, 2 );
	}

	public static function maybe_block_xmlrpc() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['block_xmlrpc'] ) ) {
			return;
		}

		add_filter( 'xmlrpc_enabled', '__return_false' );
		remove_action( 'wp_head', 'rsd_link' );
		add_filter(
			'xmlrpc_methods',
			static function ( $methods ) {
				unset( $methods['pingback.ping'], $methods['pingback.extensions.getPingbacks'] );
				return $methods;
			}
		);

		if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
			$script_name = sanitize_text_field( wp_unslash( $_SERVER['SCRIPT_NAME'] ) );
			if ( false !== strpos( $script_name, 'xmlrpc.php' ) ) {
				status_header( 403 );
				exit( esc_html__( 'XML-RPC is disabled for security reasons.', LVSW_Plugin::TEXT_DOMAIN ) );
			}
		}
	}

	public static function maybe_block_file_editing() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['block_file_mods'] ) ) {
			return;
		}

		add_filter(
			'user_has_cap',
			static function ( $allcaps ) {
				foreach ( array( 'edit_themes', 'edit_plugins', 'edit_files' ) as $cap ) {
					$allcaps[ $cap ] = false;
				}
				return $allcaps;
			},
			PHP_INT_MAX
		);

		add_filter( 'pre_option_disallow_file_edit', '__return_true' );
	}

	public static function maybe_disallow_file_mods() {
		$opts = LVSW_Plugin::get_opts();
		if ( ! empty( $opts['disallow_file_mods'] ) && ! defined( 'DISALLOW_FILE_MODS' ) ) {
			define( 'DISALLOW_FILE_MODS', true );
		}
	}

	public static function maybe_secure_head_cleanup() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['secure_head_cleanup'] ) ) {
			return;
		}
		remove_action( 'wp_head', 'rsd_link' );
		remove_action( 'wp_head', 'feed_links_extra', 3 );
		remove_action( 'wp_head', 'feed_links', 2 );
		remove_action( 'wp_head', 'wlwmanifest_link' );
		remove_action( 'wp_head', 'index_rel_link' );
		remove_action( 'wp_head', 'parent_post_rel_link', 10 );
		remove_action( 'wp_head', 'start_post_rel_link', 10 );
		remove_action( 'wp_head', 'wp_shortlink_wp_head', 10 );
		remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 );
		remove_action( 'wp_head', 'wp_generator' );
	}

	public static function maybe_hide_login_errors() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['hide_login_errors'] ) ) {
			return;
		}
		add_filter(
			'login_errors',
			static function () {
				return esc_html__( 'Login failed.', LVSW_Plugin::TEXT_DOMAIN );
			}
		);
	}

	public static function maybe_limit_login_attempts() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['limit_login_attempts'] ) ) {
			return;
		}

		$max_fails    = 3;
		$lock_minutes = 30;

		add_filter(
			'authenticate',
			static function ( $user ) use ( $max_fails, $lock_minutes ) {
				$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
				if ( empty( $ip ) ) {
					return $user;
				}
				$key   = 'lvsw_login_fail_' . md5( $ip );
				$fails = (int) get_transient( $key );
				if ( $fails >= $max_fails ) {
					return new WP_Error(
						'lvsw_too_many_attempts',
						sprintf( esc_html__( 'Too many login attempts. Please try again in %d minutes.', LVSW_Plugin::TEXT_DOMAIN ), (int) $lock_minutes )
					);
				}
				return $user;
			},
			30,
			3
		);

		add_action(
			'wp_login_failed',
			static function () use ( $max_fails, $lock_minutes ) {
				$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
				if ( empty( $ip ) ) {
					return;
				}
				$key   = 'lvsw_login_fail_' . md5( $ip );
				$fails = (int) get_transient( $key );
				$fails++;
				set_transient( $key, $fails, $lock_minutes * MINUTE_IN_SECONDS );
				if ( $fails === $max_fails ) {
					LVSW_Helpers::log_event( 'Login attempts locked for IP: ' . $ip . ' (' . $lock_minutes . ' minutes)' );
					LVSW_Helpers::record_blocked_ip( $ip );
				}
			}
		);
	}

	public static function maybe_block_pingbacks() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['block_pingbacks'] ) ) {
			return;
		}
		add_filter(
			'wp_headers',
			static function ( $headers ) {
				unset( $headers['X-Pingback'] );
				return $headers;
			}
		);
		add_filter(
			'xmlrpc_methods',
			static function ( $methods ) {
				unset( $methods['pingback.ping'], $methods['pingback.extensions.getPingbacks'] );
				return $methods;
			}
		);
		add_filter( 'pre_option_default_pingback_flag', '__return_zero' );
	}

	public static function maybe_block_user_enumeration() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['block_user_enum'] ) ) {
			return;
		}
		add_action(
			'init',
			static function () {
				if ( is_admin() ) {
					return;
				}
				if ( isset( $_GET['author'] ) && is_numeric( $_GET['author'] ) ) {
					wp_safe_redirect( home_url(), 301 );
					exit;
				}
			},
			1
		);
	}

	public static function maybe_block_comments() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['block_comments'] ) ) {
			return;
		}
		add_filter( 'comments_open', '__return_false', 20, 2 );
		add_filter( 'pings_open', '__return_false', 20, 2 );
		add_filter( 'comments_array', '__return_empty_array', 10, 2 );
		add_action(
			'admin_menu',
			static function () {
				remove_menu_page( 'edit-comments.php' );
			},
			999
		);
		add_action(
			'wp_before_admin_bar_render',
			static function () {
				global $wp_admin_bar;
				if ( is_object( $wp_admin_bar ) ) {
					$wp_admin_bar->remove_node( 'comments' );
				}
			},
			999
		);
		add_action(
			'admin_init',
			static function () {
				global $pagenow;
				if ( 'edit-comments.php' === $pagenow ) {
					wp_safe_redirect( admin_url() );
					exit;
				}
			}
		);
		add_action(
			'init',
			static function () {
				foreach ( get_post_types( array( 'public' => true ), 'names' ) as $post_type ) {
					if ( post_type_supports( $post_type, 'comments' ) ) {
						remove_post_type_support( $post_type, 'comments' );
						remove_post_type_support( $post_type, 'trackbacks' );
					}
				}
			},
			100
		);
	}

	public static function maybe_disable_application_passwords() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['disable_application_passwords'] ) ) {
			return;
		}
		add_filter( 'wp_is_application_passwords_available', '__return_false' );
	}

	public static function maybe_fix_users_can_register() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['fix_disable_user_registration'] ) ) {
			return;
		}
		if ( 1 === (int) get_option( 'users_can_register' ) ) {
			update_option( 'users_can_register', 0 );
		}
	}

	public static function maybe_block_admin_password_reset() {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['block_admin_password_reset'] ) ) {
			return;
		}
		add_filter( 'allow_password_reset', array( __CLASS__, 'filter_allow_password_reset_for_admins' ), 10, 2 );
	}

	public static function filter_allow_password_reset_for_admins( $allow, $user_id ) {
		$user = get_userdata( $user_id );
		if ( ! $user || ! ( $user instanceof WP_User ) ) {
			return $allow;
		}
		if ( in_array( 'administrator', (array) $user->roles, true ) ) {
			LVSW_Helpers::log_event( 'Blocked administrator password reset for username: ' . $user->user_login . ' (ID ' . $user->ID . ')' );
			return false;
		}
		return $allow;
	}

	public static function maybe_disable_theme_plugin_deletion() {
		// Kept for future UI-level additions.
	}

	public static function filter_caps_disable_deletion( $caps, $cap ) {
		$opts = LVSW_Plugin::get_opts();
		if ( empty( $opts['disable_deletion'] ) ) {
			return $caps;
		}
		if ( 'delete_plugins' === $cap || 'delete_themes' === $cap ) {
			return array( 'do_not_allow' );
		}
		return $caps;
	}

	public static function filter_plugin_action_links_no_delete( $actions ) {
		$opts = LVSW_Plugin::get_opts();
		if ( ! empty( $opts['disable_deletion'] ) && isset( $actions['delete'] ) ) {
			unset( $actions['delete'] );
		}
		return $actions;
	}

	public static function filter_theme_action_links_no_delete( $actions ) {
		$opts = LVSW_Plugin::get_opts();
		if ( ! empty( $opts['disable_deletion'] ) && isset( $actions['delete'] ) ) {
			unset( $actions['delete'] );
		}
		return $actions;
	}
}
