<?php
/**
 * Plugin Name: Plugin Compass Appointment manager
 * Plugin URI: https://plugincompass.com/plugins/plugin-name
 * Description: Allows users to change the URL of their wp-login page with a custom slug via an admin settings panel.
 * Version: 1.0.0
 * Author: Plugin Compass
 * Author URI: https://plugincompass.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: plugin-name
 * Domain Path: /languages
 * Update URI: false
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// Define plugin constants
define('PLUGIN_NAME_VERSION', '1.0.0');
define('PLUGIN_NAME_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('PLUGIN_NAME_PLUGIN_URL', plugin_dir_url(__FILE__));
define('PLUGIN_NAME_PLUGIN_BASENAME', plugin_basename(__FILE__));

// Prevent WordPress.org update checks
add_filter('site_transient_update_plugins', function($value) {
    $plugin_file = plugin_basename(__FILE__);
    if (isset($value->response[$plugin_file])) {
        unset($value->response[$plugin_file]);
    }
    return $value;
});

/**
 * Main Plugin Class
 */
class Plugin_Name_Login_URL_Changer {

    /**
     * Option name for storing custom login URL
     */
    const OPTION_NAME = 'plugin_name_custom_login_url';

    /**
     * Default login slug
     */
    const DEFAULT_SLUG = 'wp-login.php';

    /**
     * Instance of this class
     */
    private static $instance = null;

    /**
     * Get instance of this class
     */
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor
     */
    private function __construct() {
        $this->init();
    }

    /**
     * Initialize plugin
     */
    private function init() {
        // Admin hooks
        add_action('admin_menu', array($this, 'add_admin_menu'));
        add_action('admin_init', array($this, 'register_settings'));
        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
        add_action('admin_notices', array($this, 'display_admin_notices'));

        // Frontend hooks - URL rewriting and blocking
        add_action('init', array($this, 'handle_custom_login_url'), 1);
        add_action('login_init', array($this, 'block_default_login'), 1);
        add_filter('site_url', array($this, 'filter_login_url'), 10, 4);
        add_filter('network_site_url', array($this, 'filter_login_url'), 10, 3);
        add_filter('wp_redirect', array($this, 'filter_wp_redirect'), 10, 2);
        add_filter('lostpassword_url', array($this, 'filter_lostpassword_url'), 10, 2);
        add_filter('register_url', array($this, 'filter_register_url'), 10, 2);

        // Rewrite rules
        add_action('init', array($this, 'add_rewrite_rules'), 2);
        add_filter('query_vars', array($this, 'add_query_vars'));

    }

    /**
     * Get custom login slug
     */
    public function get_custom_slug() {
        $slug = get_option(self::OPTION_NAME, '');
        return sanitize_text_field($slug);
    }

    /**
     * Check if custom URL is enabled
     */
    public function is_custom_url_enabled() {
        $slug = $this->get_custom_slug();
        return !empty($slug) && $slug !== self::DEFAULT_SLUG;
    }

    /**
     * Get full custom login URL
     */
    public function get_custom_login_url() {
        if (!$this->is_custom_url_enabled()) {
            return wp_login_url();
        }
        $slug = $this->get_custom_slug();
        return home_url('/' . $slug);
    }

    /**
     * Add admin menu page
     */
    public function add_admin_menu() {
        add_options_page(
            __('Login URL Settings', 'plugin-name'),
            __('Login URL', 'plugin-name'),
            'manage_options',
            'plugin-name-login-url',
            array($this, 'render_settings_page')
        );
    }

    /**
     * Register settings
     */
    public function register_settings() {
        register_setting(
            'plugin_name_login_url_settings',
            self::OPTION_NAME,
            array(
                'type' => 'string',
                'sanitize_callback' => array($this, 'sanitize_login_slug'),
                'default' => ''
            )
        );
    }

    /**
     * Sanitize login slug
     */
    public function sanitize_login_slug($slug) {
        // Check nonce
        if (!isset($_POST['plugin_name_login_url_nonce']) || !wp_verify_nonce($_POST['plugin_name_login_url_nonce'], 'plugin_name_save_login_url')) {
            add_settings_error(
                'plugin_name_login_url',
                'invalid_nonce',
                __('Security check failed. Please try again.', 'plugin-name'),
                'error'
            );
            return get_option(self::OPTION_NAME, '');
        }

        // Check capabilities
        if (!current_user_can('manage_options')) {
            add_settings_error(
                'plugin_name_login_url',
                'insufficient_permissions',
                __('You do not have permission to change this setting.', 'plugin-name'),
                'error'
            );
            return get_option(self::OPTION_NAME, '');
        }

        $slug = sanitize_text_field($slug);
        $slug = trim($slug, '/');

        // If empty or default, clear the custom URL
        if (empty($slug) || $slug === 'wp-login.php' || $slug === 'wp-login') {
            add_settings_error(
                'plugin_name_login_url',
                'settings_updated',
                __('Login URL has been reset to default.', 'plugin-name'),
                'success'
            );
            return '';
        }

        // Validate slug format
        if (!preg_match('/^[a-z0-9-]+$/', $slug)) {
            add_settings_error(
                'plugin_name_login_url',
                'invalid_slug',
                __('The login URL can only contain lowercase letters, numbers, and hyphens.', 'plugin-name'),
                'error'
            );
            return get_option(self::OPTION_NAME, '');
        }

        // Check for reserved slugs
        $reserved_slugs = array(
            'wp-admin', 'wp-content', 'wp-includes',
            'admin', 'login', 'logout', 'register',
            'wp-json', 'feed', 'comments', 'trackback',
            'xmlrpc', 'wp-login', 'wp-signup', 'wp-activate'
        );

        if (in_array($slug, $reserved_slugs, true)) {
            add_settings_error(
                'plugin_name_login_url',
                'reserved_slug',
                __('This URL is reserved and cannot be used.', 'plugin-name'),
                'error'
            );
            return get_option(self::OPTION_NAME, '');
        }

        // Check for conflicts with existing pages/posts
        $existing = get_page_by_path($slug, OBJECT, array('page', 'post'));
        if ($existing) {
            add_settings_error(
                'plugin_name_login_url',
                'slug_conflict',
                __('This URL conflicts with an existing page or post.', 'plugin-name'),
                'error'
            );
            return get_option(self::OPTION_NAME, '');
        }

        // Success message
        add_settings_error(
            'plugin_name_login_url',
            'settings_updated',
            sprintf(
                __('Login URL has been changed to: %s', 'plugin-name'),
                '<code>' . esc_url(home_url('/' . $slug)) . '</code>'
            ),
            'success'
        );

        return $slug;
    }

    /**
     * Render settings page
     */
    public function render_settings_page() {
        if (!current_user_can('manage_options')) {
            return;
        }

        $current_slug = $this->get_custom_slug();
        $custom_url = $this->get_custom_login_url();
        $is_custom = $this->is_custom_url_enabled();
        ?>
        <div class="wrap plugin-name-wrap">
            <h1><?php echo esc_html(get_admin_page_title()); ?></h1>

            <?php settings_errors('plugin_name_login_url'); ?>

            <div class="plugin-name-card">
                <h2><?php _e('Custom Login URL', 'plugin-name'); ?></h2>
                <p><?php _e('Change the URL of your WordPress login page to improve security and prevent automated attacks.', 'plugin-name'); ?></p>

                <?php if ($is_custom) : ?>
                <div class="plugin-name-notice plugin-name-notice-warning">
                    <span class="dashicons dashicons-warning"></span>
                    <p>
                        <strong><?php _e('Important:', 'plugin-name'); ?></strong>
                        <?php _e('Your login URL has been changed. Make sure to bookmark the new URL:', 'plugin-name'); ?>
                        <br>
                        <code class="plugin-name-url"><?php echo esc_url($custom_url); ?></code>
                    </p>
                </div>
                <?php endif; ?>

                <form method="post" action="options.php">
                    <?php wp_nonce_field('plugin_name_save_login_url', 'plugin_name_login_url_nonce'); ?>
                    <?php settings_fields('plugin_name_login_url_settings'); ?>

                    <table class="form-table">
                        <tr>
                            <th scope="row">
                                <label for="<?php echo esc_attr(self::OPTION_NAME); ?>">
                                    <?php _e('Custom Login Slug', 'plugin-name'); ?>
                                </label>
                            </th>
                            <td>
                                <div class="plugin-name-input-group">
                                    <span class="plugin-name-input-prefix"><?php echo esc_url(home_url('/')); ?></span>
                                    <input type="text"
                                           id="<?php echo esc_attr(self::OPTION_NAME); ?>"
                                           name="<?php echo esc_attr(self::OPTION_NAME); ?>"
                                           value="<?php echo esc_attr($current_slug); ?>"
                                           class="regular-text"
                                           placeholder="my-secret-login"
                                           pattern="[a-z0-9-]+"
                                           title="<?php esc_attr_e('Only lowercase letters, numbers, and hyphens allowed', 'plugin-name'); ?>">
                                </div>
                                <p class="description">
                                    <?php _e('Enter a custom slug for your login page (e.g., my-secret-login). Use only lowercase letters, numbers, and hyphens.', 'plugin-name'); ?>
                                </p>
                                <?php if ($is_custom) : ?>
                                <p class="description">
                                    <?php _e('Leave empty and save to reset to default wp-login.php', 'plugin-name'); ?>
                                </p>
                                <?php endif; ?>
                            </td>
                        </tr>
                    </table>

                    <?php submit_button($is_custom ? __('Update Login URL', 'plugin-name') : __('Save Login URL', 'plugin-name')); ?>
                </form>
            </div>

            <div class="plugin-name-card plugin-name-card-info">
                <h3><?php _e('Current Login URLs', 'plugin-name'); ?></h3>
                <table class="widefat plugin-name-table">
                    <tbody>
                        <tr>
                            <td><strong><?php _e('Custom Login URL:', 'plugin-name'); ?></strong></td>
                            <td>
                                <?php if ($is_custom) : ?>
                                    <code><?php echo esc_url($custom_url); ?></code>
                                    <a href="<?php echo esc_url($custom_url); ?>" class="button button-small" target="_blank">
                                        <?php _e('Visit', 'plugin-name'); ?>
                                    </a>
                                <?php else : ?>
                                    <em><?php _e('Not set (using default)', 'plugin-name'); ?></em>
                                <?php endif; ?>
                            </td>
                        </tr>
                        <tr>
                            <td><strong><?php _e('Default Login URL:', 'plugin-name'); ?></strong></td>
                            <td>
                                <code><?php echo esc_url(wp_login_url()); ?></code>
                                <?php if ($is_custom) : ?>
                                    <span class="plugin-name-badge plugin-name-badge-blocked"><?php _e('Blocked', 'plugin-name'); ?></span>
                                <?php else : ?>
                                    <span class="plugin-name-badge plugin-name-badge-active"><?php _e('Active', 'plugin-name'); ?></span>
                                <?php endif; ?>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <div class="plugin-name-card plugin-name-card-help">
                <h3><?php _e('Help & Information', 'plugin-name'); ?></h3>
                <ul>
                    <li><?php _e('The custom login URL will replace the default wp-login.php', 'plugin-name'); ?></li>
                    <li><?php _e('The old wp-login.php URL will be blocked when a custom URL is set', 'plugin-name'); ?></li>
                    <li><?php _e('Make sure to bookmark your new login URL before logging out', 'plugin-name'); ?></li>
                    <li><?php _e('If you forget your custom URL, you can disable this plugin via FTP or database to restore default access', 'plugin-name'); ?></li>
                </ul>
            </div>
        </div>
        <?php
    }

    /**
     * Enqueue admin assets
     */
    public function enqueue_admin_assets($hook) {
        if ('settings_page_plugin-name-login-url' !== $hook) {
            return;
        }

        wp_enqueue_style(
            'plugin-name-admin-css',
            PLUGIN_NAME_PLUGIN_URL . 'admin/css/admin-style.css',
            array(),
            PLUGIN_NAME_VERSION
        );
    }

    /**
     * Display admin notices
     */
    public function display_admin_notices() {
        $screen = get_current_screen();
        if (!$screen || $screen->id !== 'settings_page_plugin-name-login-url') {
            return;
        }

        // Only show on the settings page if settings_errors hasn't already shown
    }

    /**
     * Add rewrite rules for custom login URL
     */
    public function add_rewrite_rules() {
        $slug = $this->get_custom_slug();
        if (empty($slug)) {
            return;
        }

        add_rewrite_rule(
            '^' . $slug . '/?$',
            'index.php?plugin_name_login=1',
            'top'
        );

        add_rewrite_rule(
            '^' . $slug . '/([^/]+)/?$',
            'index.php?plugin_name_login=1&action=$matches[1]',
            'top'
        );
    }

    /**
     * Add custom query vars
     */
    public function add_query_vars($vars) {
        $vars[] = 'plugin_name_login';
        return $vars;
    }

    /**
     * Handle custom login URL
     */
    public function handle_custom_login_url() {
        // Check query var (for when rewrite rules work)
        $has_query_var = get_query_var('plugin_name_login');
        
        // Fallback: check REQUEST_URI directly (for when rewrite rules don't work)
        $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field($_SERVER['REQUEST_URI']) : '';
        $custom_slug = $this->get_custom_slug();
        
        // Remove query string for comparison
        $request_path = strtok($request_uri, '?');
        $request_path = trim($request_path, '/');
        
        // Check if we're accessing the custom slug directly
        $is_custom_url = !empty($custom_slug) && ($request_path === $custom_slug || preg_match('#^' . preg_quote($custom_slug, '#') . '(/.*)?$#', $request_path));
        
        if (!$has_query_var && !$is_custom_url) {
            return;
        }
        
        // Set the query var for compatibility
        if ($is_custom_url && !$has_query_var) {
            set_query_var('plugin_name_login', 1);
            // Extract action from URL if present
            $action = 'login';
            if (preg_match('#^' . preg_quote($custom_slug, '#') . '/([^/]+)#', $request_path, $matches)) {
                $action = $matches[1];
            }
            set_query_var('action', $action);
        }

        // Prevent caching
        nocache_headers();

        $action = get_query_var('action') ? get_query_var('action') : 'login';

        // Set up login globals that wp-login.php expects
        global $error, $interim_login, $action;
        
        // Parse any login errors from query string
        $error = '';
        if (!empty($_GET['login'])) {
            $login = sanitize_text_field($_GET['login']);
            switch ($login) {
                case 'failed':
                    $error = __('<strong>Error:</strong> Invalid username or password.', 'plugin-name');
                    break;
                case 'empty':
                    $error = __('<strong>Error:</strong> Username and password are required.', 'plugin-name');
                    break;
                case 'loggedout':
                    $error = __('You are now logged out.', 'plugin-name');
                    break;
                case 'expired':
                    $error = __('Your session has expired. Please log in again.', 'plugin-name');
                    break;
            }
        }

        // Re-login for interim login
        $interim_login = isset($_REQUEST['interim-login']);

        // Handle POST requests (form submissions)
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['log'])) {
            $this->handle_login_post();
            return;
        }

        // Display the login form
        $this->render_login_form($action, $error);
        exit;
    }

    /**
     * Handle login form POST submission
     */
    private function handle_login_post() {
        $user_login = isset($_POST['log']) ? sanitize_user($_POST['log']) : '';
        $user_pass = isset($_POST['pwd']) ? $_POST['pwd'] : '';
        $remember = isset($_POST['rememberme']) ? true : false;

        $credentials = array(
            'user_login'    => $user_login,
            'user_password' => $user_pass,
            'remember'      => $remember
        );

        $user = wp_signon($credentials, is_ssl());

        if (is_wp_error($user)) {
            // Redirect back to custom login with error
            $redirect_to = $this->get_custom_login_url();
            wp_redirect(add_query_arg('login', 'failed', $redirect_to));
            exit;
        }

        // Successful login - redirect to admin or requested location
        $redirect_to = isset($_POST['redirect_to']) ? esc_url_raw($_POST['redirect_to']) : admin_url();
        wp_redirect($redirect_to);
        exit;
    }

    /**
     * Render the login form
     */
    private function render_login_form($action, $error) {
        $custom_slug = $this->get_custom_slug();
        $login_url = $this->get_custom_login_url();
        $redirect_to = isset($_REQUEST['redirect_to']) ? esc_url_raw($_REQUEST['redirect_to']) : admin_url();
        
        // Output login form
        ?>
        <!DOCTYPE html>
        <html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
        <head>
            <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
            <title><?php bloginfo('name'); ?> &rsaquo; Log In</title>
            <?php
            wp_enqueue_style('login');
            wp_enqueue_script('user-profile');
            do_action('login_enqueue_scripts');
            do_action('login_head');
            ?>
        </head>
        <body class="login wp-core-ui">
            <div id="login">
                <h1><a href="<?php echo esc_url(apply_filters('login_headerurl', home_url())); ?>"><?php echo get_bloginfo('name', 'display'); ?></a></h1>
                
                <?php if (!empty($error)) : ?>
                    <div id="login_error"><?php echo $error; ?></div>
                <?php endif; ?>
                
                <form name="loginform" id="loginform" action="<?php echo esc_url($login_url); ?>" method="post">
                    <p>
                        <label for="user_login">Username or Email Address<br />
                        <input type="text" name="log" id="user_login" class="input" value="<?php echo esc_attr(isset($_POST['log']) ? $_POST['log'] : ''); ?>" size="20" autocapitalize="off" /></label>
                    </p>
                    <p>
                        <label for="user_pass">Password<br />
                        <input type="password" name="pwd" id="user_pass" class="input" value="" size="20" /></label>
                    </p>
                    <?php do_action('login_form'); ?>
                    <p class="forgetmenot">
                        <label for="rememberme"><input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked(isset($_POST['rememberme'])); ?> /> Remember Me</label>
                    </p>
                    <p class="submit">
                        <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="Log In" />
                        <input type="hidden" name="redirect_to" value="<?php echo esc_url($redirect_to); ?>" />
                    </p>
                </form>
                
                <p id="nav">
                    <a href="<?php echo esc_url(wp_lostpassword_url()); ?>">Lost your password?</a>
                </p>
                
                <p id="backtoblog">
                    <a href="<?php echo esc_url(home_url('/')); ?>">&larr; Back to <?php echo get_bloginfo('name', 'display'); ?></a>
                </p>
            </div>
            
            <?php do_action('login_footer'); ?>
            <?php wp_footer(); ?>
        </body>
        </html>
        <?php
    }

    /**
     * Block default login when custom URL is set
     */
    public function block_default_login() {
        if (!$this->is_custom_url_enabled()) {
            return;
        }

        // Allow access for certain actions that need wp-login.php
        $allowed_actions = array('logout', 'postpass', 'rp', 'resetpass');
        $action = isset($_REQUEST['action']) ? sanitize_text_field($_REQUEST['action']) : 'login';

        if (in_array($action, $allowed_actions, true)) {
            return;
        }

        // Check if this is the real wp-login.php file (not our custom URL)
        $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field($_SERVER['REQUEST_URI']) : '';
        $custom_slug = $this->get_custom_slug();

        if (strpos($request_uri, 'wp-login.php') !== false && strpos($request_uri, $custom_slug) === false) {
            // Return 404 or redirect to custom URL
            wp_redirect(home_url('/404'), 404);
            exit;
        }
    }

    /**
     * Filter login URL
     */
    public function filter_login_url($url, $path, $scheme = null, $blog_id = null) {
        if (!$this->is_custom_url_enabled()) {
            return $url;
        }

        // Only filter wp-login.php URLs
        if (strpos($url, 'wp-login.php') === false) {
            return $url;
        }

        $custom_slug = $this->get_custom_slug();
        $custom_url = str_replace('wp-login.php', $custom_slug, $url);

        return $custom_url;
    }

    /**
     * Filter wp_redirect
     */
    public function filter_wp_redirect($location, $status) {
        if (!$this->is_custom_url_enabled()) {
            return $location;
        }

        // Replace wp-login.php with custom slug in redirects
        if (strpos($location, 'wp-login.php') !== false) {
            $custom_slug = $this->get_custom_slug();
            $location = str_replace('wp-login.php', $custom_slug, $location);
        }

        return $location;
    }

    /**
     * Filter lostpassword URL
     */
    public function filter_lostpassword_url($url, $redirect) {
        if (!$this->is_custom_url_enabled()) {
            return $url;
        }

        $custom_slug = $this->get_custom_slug();
        return str_replace('wp-login.php', $custom_slug, $url);
    }

    /**
     * Filter register URL
     */
    public function filter_register_url($url) {
        if (!$this->is_custom_url_enabled()) {
            return $url;
        }

        $custom_slug = $this->get_custom_slug();
        return str_replace('wp-login.php', $custom_slug, $url);
    }

}

// Initialize plugin
add_action('plugins_loaded', array('Plugin_Name_Login_URL_Changer', 'get_instance'));

// Activation hook - must be outside class
register_activation_hook(__FILE__, 'plugin_name_activate');
function plugin_name_activate() {
    // Make sure rewrite rules are regenerated
    global $wp_rewrite;
    if ($wp_rewrite) {
        $wp_rewrite->flush_rules(true);
    } else {
        flush_rewrite_rules(true);
    }
}

// Deactivation hook - must be outside class
register_deactivation_hook(__FILE__, 'plugin_name_deactivate');
function plugin_name_deactivate() {
    // Flush rewrite rules to remove custom rules
    flush_rewrite_rules();
}

// Flush rewrite rules after option is updated
add_action('update_option_plugin_name_custom_login_url', 'plugin_name_flush_after_update', 10, 2);
function plugin_name_flush_after_update($old_value, $new_value) {
    // Only flush if value actually changed
    if ($old_value !== $new_value) {
        // Use a transient to delay the flush until after the page loads
        set_transient('plugin_name_needs_flush', true, 60);
    }
}

// Perform the actual flush on the next admin load
add_action('admin_init', 'plugin_name_perform_flush');
function plugin_name_perform_flush() {
    if (get_transient('plugin_name_needs_flush')) {
        delete_transient('plugin_name_needs_flush');
        flush_rewrite_rules(true);
    }
}
