<?php

namespace VulnTitan\Services;

class LoginAccessService
{
    protected const PUBLIC_ADMIN_SCRIPTS = [
        'admin-ajax.php',
        'admin-post.php',
        'load-scripts.php',
        'load-styles.php',
    ];

    protected static bool $booted = false;
    protected static bool $customLoginRequest = false;
    protected static bool $customLoginContextPrimed = false;

    public static function boot(): void
    {
        if (self::$booted) {
            return;
        }

        self::$booted = true;
        self::primeCustomLoginRequestContext();

        add_action('init', [__CLASS__, 'interceptRequests'], 0);
        add_action('wp_loaded', [__CLASS__, 'maybeRenderCustomLogin'], 0);
        add_filter('site_url', [__CLASS__, 'filterSiteUrl'], 10, 4);
        add_filter('network_site_url', [__CLASS__, 'filterNetworkSiteUrl'], 10, 3);
        add_filter('login_url', [__CLASS__, 'replaceGeneratedLoginUrl'], 10, 3);
        add_filter('logout_url', [__CLASS__, 'replaceGeneratedLoginUrl'], 10, 2);
        add_filter('lostpassword_url', [__CLASS__, 'replaceGeneratedLoginUrl'], 10, 2);
        add_filter('register_url', [__CLASS__, 'replaceGeneratedLoginUrl']);
        add_filter('lostpassword_redirect', [__CLASS__, 'filterLostPasswordRedirect']);
        add_filter('wp_redirect', [__CLASS__, 'replaceGeneratedLoginUrl'], 10, 2);
    }

    public static function interceptRequests(): void
    {
        if (!FirewallService::isCustomLoginEnabled()) {
            return;
        }

        if ((defined('WP_CLI') && WP_CLI) || (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST)) {
            return;
        }

        $requestPath = self::getCurrentRequestPath();
        if ($requestPath === '') {
            return;
        }

        if (self::isCustomLoginPath($requestPath)) {
            self::markCustomLoginRequest();
            return;
        }

        if (self::isDefaultLoginPath($requestPath)) {
            self::denyAccess(
                'default_login_path',
                'Blocked direct access to the default WordPress login path.',
                'wp-login.php'
            );
        }

        if (self::isProtectedAdminPath($requestPath)) {
            self::denyAccess(
                'default_admin_path',
                'Blocked direct access to the default WordPress admin path for a logged-out visitor.',
                'wp-admin'
            );
        }
    }

    public static function maybeRenderCustomLogin(): void
    {
        if (!self::$customLoginRequest) {
            return;
        }

        self::maybeRedirectCanonicalCustomLoginPath();
        self::primeCustomLoginContext();

        global $pagenow, $action, $error, $interim_login, $user_login;

        $pagenow = 'wp-login.php';
        $action = is_string($action ?? null) && $action !== '' ? $action : 'login';
        $error = is_string($error ?? null) ? $error : '';
        $interim_login = $interim_login ?? false;
        $user_login = is_string($user_login ?? null) ? $user_login : '';

        require_once ABSPATH . 'wp-login.php';
        exit;
    }

    public static function filterSiteUrl($url, $path, $scheme, $blogId)
    {
        if (!FirewallService::isCustomLoginEnabled() || !is_string($path)) {
            return $url;
        }

        $replacement = self::buildCustomLoginUrlFromPath($path, is_string($scheme) ? $scheme : 'login');

        return $replacement !== '' ? $replacement : $url;
    }

    public static function filterNetworkSiteUrl($url, $path, $scheme)
    {
        if (!FirewallService::isCustomLoginEnabled() || !is_string($path)) {
            return $url;
        }

        $replacement = self::buildCustomLoginUrlFromPath($path, is_string($scheme) ? $scheme : 'login', true);

        return $replacement !== '' ? $replacement : $url;
    }

    public static function replaceGeneratedLoginUrl($url)
    {
        if (!FirewallService::isCustomLoginEnabled() || !is_string($url) || $url === '') {
            return $url;
        }

        $relativeMatch = [];
        $relativePattern = self::getRelativeLoginUrlPattern();
        if ($relativePattern !== '' && preg_match($relativePattern, $url, $relativeMatch)) {
            $queryArgs = [];
            if (!empty($relativeMatch[1])) {
                parse_str((string) $relativeMatch[1], $queryArgs);
            }

            $customUrl = FirewallService::getCustomLoginUrl($queryArgs);
            if ($customUrl === '') {
                return $url;
            }

            if (!empty($relativeMatch[2])) {
                $customUrl .= '#' . (string) $relativeMatch[2];
            }

            return $customUrl;
        }

        $parts = wp_parse_url($url);
        if (!is_array($parts)) {
            return $url;
        }

        $requestPath = self::stripSiteBasePath((string) ($parts['path'] ?? ''));
        if (!self::isLoginRewriteCandidatePath($requestPath)) {
            return $url;
        }

        $scheme = (string) ($parts['scheme'] ?? '');
        $customUrl = FirewallService::getCustomLoginUrl([], $scheme !== '' ? $scheme : 'login');
        if ($customUrl === '') {
            return $url;
        }

        if (!empty($parts['query'])) {
            parse_str((string) $parts['query'], $queryArgs);
            if ($queryArgs) {
                $customUrl = add_query_arg($queryArgs, $customUrl);
            }
        }

        if (!empty($parts['fragment'])) {
            $customUrl .= '#' . (string) $parts['fragment'];
        }

        return $customUrl;
    }

    public static function filterLostPasswordRedirect($redirectTo)
    {
        if (!FirewallService::isCustomLoginEnabled()) {
            return $redirectTo;
        }

        if (!is_string($redirectTo) || trim($redirectTo) === '') {
            return FirewallService::getCustomLoginUrl([
                'checkemail' => 'confirm',
            ]);
        }

        return self::replaceGeneratedLoginUrl($redirectTo);
    }

    protected static function buildCustomLoginUrlFromPath(string $path, string $scheme = 'login', bool $network = false): string
    {
        $pattern = self::getRelativeLoginUrlPattern();
        $matches = [];

        if ($pattern === '' || !preg_match($pattern, ltrim($path, '/'), $matches)) {
            return '';
        }

        $slug = FirewallService::getCustomLoginSlug();
        if ($slug === '') {
            return '';
        }

        $customUrl = $network && function_exists('network_home_url')
            ? network_home_url('/' . user_trailingslashit($slug), $scheme)
            : FirewallService::getCustomLoginUrl([], $scheme);

        if ($customUrl === '') {
            return '';
        }

        $queryString = isset($matches[1]) ? (string) $matches[1] : '';
        if ($queryString !== '') {
            parse_str($queryString, $queryArgs);
            if ($queryArgs) {
                $customUrl = add_query_arg($queryArgs, $customUrl);
            }
        }

        return $customUrl;
    }

    protected static function primeCustomLoginRequestContext(): void
    {
        if (!FirewallService::isCustomLoginEnabled()) {
            return;
        }

        if ((defined('WP_CLI') && WP_CLI) || (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST)) {
            return;
        }

        $requestPath = self::getCurrentRequestPath();
        if ($requestPath === '' || !self::isCustomLoginPath($requestPath)) {
            return;
        }

        self::markCustomLoginRequest();
    }

    protected static function markCustomLoginRequest(): void
    {
        self::$customLoginRequest = true;
        self::primeCustomLoginContext();
    }

    protected static function primeCustomLoginContext(): void
    {
        if (self::$customLoginContextPrimed) {
            return;
        }

        self::$customLoginContextPrimed = true;

        global $pagenow;

        $pagenow = 'wp-login.php';

        $scriptPath = self::getWpLoginScriptPath();
        if ($scriptPath !== '') {
            $_SERVER['SCRIPT_NAME'] = $scriptPath;
            $_SERVER['PHP_SELF'] = $scriptPath;
        }
    }

    protected static function maybeRedirectCanonicalCustomLoginPath(): void
    {
        if (!get_option('permalink_structure')) {
            return;
        }

        if (strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) !== 'GET') {
            return;
        }

        $requestPath = self::getCurrentRequestPath();
        $canonicalPath = self::stripSiteBasePath((string) wp_parse_url(FirewallService::getCustomLoginUrl(), PHP_URL_PATH));
        if ($requestPath === '' || $canonicalPath === '') {
            return;
        }

        if ($requestPath === $canonicalPath || untrailingslashit($requestPath) !== untrailingslashit($canonicalPath)) {
            return;
        }

        $redirectUrl = FirewallService::getCustomLoginUrl();
        $queryString = (string) ($_SERVER['QUERY_STRING'] ?? '');
        if ($queryString !== '') {
            $redirectUrl .= '?' . $queryString;
        }

        wp_safe_redirect($redirectUrl);
        exit;
    }

    protected static function getRelativeLoginUrlPattern(): string
    {
        $slug = trim(FirewallService::getCustomLoginSlug(), '/');
        $prefix = '';

        if ($slug !== '') {
            $prefix = '(?:' . preg_quote($slug, '~') . '/)?';
        }

        return '~^/?' . $prefix . 'wp-login\.php(?:\?([^#]*))?(?:#(.*))?$~i';
    }

    protected static function isCustomLoginPath(string $requestPath): bool
    {
        $slug = trim(FirewallService::getCustomLoginSlug(), '/');
        if ($slug === '') {
            return false;
        }

        return trim($requestPath, '/') === $slug;
    }

    protected static function isDefaultLoginPath(string $requestPath): bool
    {
        $normalized = strtolower($requestPath);

        return $normalized === '/wp-login.php' || strpos($normalized, '/wp-login.php') === 0;
    }

    protected static function isLoginRewriteCandidatePath(string $requestPath): bool
    {
        if (self::isDefaultLoginPath($requestPath)) {
            return true;
        }

        $slug = trim(FirewallService::getCustomLoginSlug(), '/');
        if ($slug === '') {
            return false;
        }

        $normalized = strtolower('/' . ltrim($requestPath, '/'));
        $nestedPath = '/' . strtolower($slug) . '/wp-login.php';

        return $normalized === $nestedPath || strpos($normalized, $nestedPath . '?') === 0 || strpos($normalized, $nestedPath . '/') === 0;
    }

    protected static function isProtectedAdminPath(string $requestPath): bool
    {
        if (is_user_logged_in()) {
            return false;
        }

        $normalized = strtolower($requestPath);
        if ($normalized !== '/wp-admin' && $normalized !== '/wp-admin/' && strpos($normalized, '/wp-admin/') !== 0) {
            return false;
        }

        if ((function_exists('wp_doing_ajax') && wp_doing_ajax()) || (defined('DOING_CRON') && DOING_CRON)) {
            return false;
        }

        if (preg_match('#^/wp-admin/(?:css|images|js)/#', $normalized)) {
            return false;
        }

        if (preg_match('/\.(?:css|js|png|gif|svg|jpg|jpeg|webp|woff2?|ttf|eot)$/', $normalized)) {
            return false;
        }

        $scriptName = strtolower(basename((string) ($_SERVER['SCRIPT_NAME'] ?? '')));

        return !in_array($scriptName, self::PUBLIC_ADMIN_SCRIPTS, true);
    }

    protected static function getCurrentRequestPath(): string
    {
        $requestUri = (string) ($_SERVER['REQUEST_URI'] ?? '');
        if ($requestUri === '') {
            return '';
        }

        $path = (string) (parse_url($requestUri, PHP_URL_PATH) ?: '');

        return self::stripSiteBasePath($path);
    }

    protected static function stripSiteBasePath(string $path): string
    {
        $normalizedPath = '/' . ltrim($path, '/');
        $sitePath = (string) wp_parse_url(home_url('/'), PHP_URL_PATH);
        $sitePath = '/' . trim($sitePath, '/');
        $sitePath = $sitePath === '//' ? '/' : $sitePath;

        if ($sitePath !== '/' && strpos($normalizedPath, $sitePath) === 0) {
            $normalizedPath = substr($normalizedPath, strlen($sitePath));
        }

        if ($normalizedPath === '' || $normalizedPath === false) {
            return '/';
        }

        return '/' . ltrim($normalizedPath, '/');
    }

    protected static function getWpLoginScriptPath(): string
    {
        $sitePath = (string) wp_parse_url(site_url('/'), PHP_URL_PATH);
        $sitePath = '/' . trim($sitePath, '/');
        $sitePath = $sitePath === '//' ? '/' : $sitePath;

        if ($sitePath === '/') {
            return '/wp-login.php';
        }

        return rtrim($sitePath, '/') . '/wp-login.php';
    }

    protected static function denyAccess(string $ruleId, string $reason, string $matchedPattern): void
    {
        FirewallService::logEvent('request_blocked', [
            'ip_address' => FirewallService::detectClientIp(),
            'reason' => $reason,
            'request_uri' => (string) ($_SERVER['REQUEST_URI'] ?? ''),
            'event_source' => 'login_access',
            'rule_group' => 'login_access',
            'rule_id' => $ruleId,
            'matched_pattern' => $matchedPattern,
            'response_code' => 404,
            'blocked' => 1,
            'details' => [
                'request_path' => self::getCurrentRequestPath(),
            ],
        ]);

        self::renderNotFound();
    }

    protected static function renderNotFound(): void
    {
        $charset = function_exists('get_bloginfo') ? (string) get_bloginfo('charset') : 'UTF-8';
        $siteName = function_exists('get_bloginfo') ? (string) get_bloginfo('name') : 'WordPress';
        $homeUrl = function_exists('home_url') ? (string) home_url('/') : '/';
        $brandUrl = 'https://vulntitan.com';
        $logoUrl = defined('VULNTITAN_PLUGIN_URL')
            ? (string) VULNTITAN_PLUGIN_URL . '/assets/img/vulntitan-logo-2.png'
            : '';

        status_header(404);
        nocache_headers();
        header('X-Robots-Tag: noindex, nofollow', true);
        header('Content-Type: text/html; charset=' . $charset);

        echo '<!DOCTYPE html>'
            . '<html lang="en">'
            . '<head>'
            . '<meta charset="' . esc_attr($charset) . '">'
            . '<meta name="viewport" content="width=device-width, initial-scale=1">'
            . '<title>Protected Access</title>'
            . '<style>'
            . 'html{font-size:16px}'
            . 'body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;background:radial-gradient(circle at top,#18345f 0%,#081424 38%,#03070d 100%);color:#e5eef8;font-family:"Avenir Next","Helvetica Neue","Segoe UI",sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:relative;overflow:hidden}'
            . 'body:before{content:"";position:fixed;inset:0;background:linear-gradient(rgba(143,215,255,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(143,215,255,.05) 1px,transparent 1px);background-size:48px 48px;mask-image:radial-gradient(circle at center,black 30%,transparent 80%);pointer-events:none}'
            . 'body:after{content:"";position:fixed;width:34rem;height:34rem;right:-9rem;top:-8rem;border-radius:50%;background:radial-gradient(circle,rgba(82,171,255,.18) 0%,rgba(82,171,255,0) 68%);filter:blur(10px);pointer-events:none}'
            . '.vt404{width:100%;max-width:860px;position:relative;border:1px solid rgba(143,215,255,.16);border-radius:30px;background:linear-gradient(180deg,rgba(8,17,30,.96) 0%,rgba(4,10,18,.92) 100%);box-shadow:0 28px 100px rgba(0,0,0,.52),inset 0 1px 0 rgba(255,255,255,.04);overflow:hidden}'
            . '.vt404:before{content:"";position:absolute;inset:0;background:linear-gradient(135deg,rgba(61,181,255,.09) 0%,transparent 28%,transparent 72%,rgba(88,209,255,.08) 100%);pointer-events:none}'
            . '.vt404-topbar{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 22px;border-bottom:1px solid rgba(143,215,255,.12);background:linear-gradient(180deg,rgba(13,28,48,.92) 0%,rgba(8,17,30,.4) 100%)}'
            . '.vt404-brand{display:flex;align-items:center;gap:14px;min-width:0}'
            . '.vt404-brand img{display:block;width:148px;max-width:42vw;height:auto;filter:drop-shadow(0 8px 18px rgba(0,0,0,.28))}'
            . '.vt404-brand-copy{min-width:0}'
            . '.vt404-brand-kicker{display:block;font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:#93cfff;font-weight:700;opacity:.82}'
            . '.vt404-brand-site{display:block;margin-top:3px;font-size:17px;line-height:1.1;font-weight:700;letter-spacing:.01em;color:#f8fbff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}'
            . '.vt404-status{display:inline-flex;align-items:center;gap:8px;padding:9px 13px;border-radius:999px;border:1px solid rgba(82,171,255,.24);background:rgba(82,171,255,.1);font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#9fd2ff}'
            . '.vt404-status-dot{width:8px;height:8px;border-radius:999px;background:#58d1ff;box-shadow:0 0 18px rgba(88,209,255,.8)}'
            . '.vt404-body{position:relative;z-index:1;padding:28px 30px 18px;text-align:center}'
            . '.vt404-eyebrow{display:inline-flex;align-items:center;gap:10px;padding:8px 12px;border-radius:999px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);font-size:11px;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:#bfdfff}'
            . '.vt404-code{margin:14px 0 0;font-size:clamp(3.2rem,9vw,5.25rem);line-height:.94;font-weight:700;letter-spacing:-.04em;color:#fff;text-shadow:0 8px 24px rgba(61,181,255,.14);font-family:"Avenir Next","Helvetica Neue","Segoe UI",sans-serif}'
            . '.vt404-title{margin:12px 0 10px;font-size:clamp(1.35rem,3vw,2.05rem);line-height:1.14;font-weight:600;color:#f8fbff;font-family:"Avenir Next","Helvetica Neue","Segoe UI",sans-serif}'
            . '.vt404-text{margin:0 auto;max-width:32rem;font-size:.95rem;line-height:1.6;color:#a9bbce}'
            . '.vt404-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:18px}'
            . '.vt404-chip{display:inline-flex;align-items:center;padding:8px 12px;border-radius:999px;border:1px solid rgba(143,215,255,.14);background:rgba(255,255,255,.03);font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#9fc0da}'
            . '.vt404-actions{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:24px}'
            . '.vt404-cta{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:0 18px;border-radius:12px;border:1px solid transparent;text-decoration:none;font-size:13px;font-weight:700;letter-spacing:.01em;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease,background .18s ease,color .18s ease}'
            . '.vt404-cta:hover{transform:translateY(-1px)}'
            . '.vt404-cta:after{content:"\\2192";margin-left:8px;font-size:13px;opacity:.9}'
            . '.vt404-cta-primary{border-color:rgba(124,216,255,.28);background:linear-gradient(180deg,rgba(93,212,255,.22) 0%,rgba(36,129,196,.18) 100%);color:#f7fcff;box-shadow:0 10px 24px rgba(18,88,140,.24),inset 0 1px 0 rgba(255,255,255,.08)}'
            . '.vt404-cta-primary:hover{border-color:rgba(124,216,255,.42);box-shadow:0 14px 28px rgba(18,88,140,.3),inset 0 1px 0 rgba(255,255,255,.1)}'
            . '.vt404-cta-secondary{border-color:rgba(143,215,255,.14);background:rgba(255,255,255,.035);color:#dcecf8;box-shadow:0 8px 18px rgba(0,0,0,.16),inset 0 1px 0 rgba(255,255,255,.04)}'
            . '.vt404-cta-secondary:hover{border-color:rgba(143,215,255,.24);background:rgba(255,255,255,.05);box-shadow:0 12px 22px rgba(0,0,0,.2),inset 0 1px 0 rgba(255,255,255,.05)}'
            . '.vt404-footer{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:64px;padding:10px 30px 12px;color:#7f96ac;font-size:.86rem;border-top:1px solid rgba(143,215,255,.08)}'
            . '.vt404-footer>div{display:flex;align-items:center;min-height:40px}'
            . '.vt404-footer-brand{gap:6px}'
            . '.vt404-footer a{color:#8fd7ff;text-decoration:none}'
            . '.vt404-footer a:hover{text-decoration:underline}'
            . '@media (max-width:760px){body{padding:16px}.vt404-topbar,.vt404-body,.vt404-footer{padding-left:20px;padding-right:20px}.vt404-topbar,.vt404-footer{display:block}.vt404-status{margin-top:16px}.vt404-actions{display:grid}.vt404-cta{width:100%}.vt404-footer{padding-top:14px;padding-bottom:18px}.vt404-footer div+div{margin-top:10px}}'
            . '</style>'
            . '</head>'
            . '<body>'
            . '<main class="vt404" aria-labelledby="vt404-title">'
            . '<div class="vt404-topbar">'
            . '<div class="vt404-brand">';

        if ($logoUrl !== '') {
            echo '<img src="' . esc_url($logoUrl) . '" alt="VulnTitan">';
        }

        echo '<div class="vt404-brand-copy">'
            . '<span class="vt404-brand-kicker">Security</span>'
            . '<span class="vt404-brand-site">VulnTitan</span>'
            . '</div>'
            . '</div>'
            . '<div class="vt404-status"><span class="vt404-status-dot" aria-hidden="true"></span>Security Shield</div>'
            . '</div>'
            . '<div class="vt404-body">'
            . '<div class="vt404-eyebrow">VulnTitan Access Shield</div>'
            . '<h1 class="vt404-code">Shield</h1>'
            . '<h2 id="vt404-title" class="vt404-title">Protected Access</h2>'
            . '<p class="vt404-text">This route is secured by VulnTitan and is not exposed publicly.</p>'
            . '<div class="vt404-chips">'
            . '<span class="vt404-chip">Route Hidden</span>'
            . '<span class="vt404-chip">Access Guard</span>'
            . '<span class="vt404-chip">VulnTitan</span>'
            . '</div>'
            . '<div class="vt404-actions">'
            . '<a class="vt404-cta vt404-cta-primary" href="' . esc_url($homeUrl) . '">Return to Homepage</a>'
            . '<a class="vt404-cta vt404-cta-secondary" href="' . esc_url($brandUrl) . '" target="_blank" rel="noopener noreferrer">Learn About VulnTitan</a>'
            . '</div>'
            . '</div>'
            . '<div class="vt404-footer">'
            . '<div>Protected endpoint</div>'
            . '<div class="vt404-footer-brand"><span>Powered by</span><a href="' . esc_url($brandUrl) . '" target="_blank" rel="noopener noreferrer">VulnTitan.com</a></div>'
            . '</div>'
            . '</main>'
            . '</body>'
            . '</html>';
        exit;
    }
}
