<?php

declare(strict_types=1);

namespace ShieldX\Admin;

defined('ABSPATH') || exit;

use ShieldX\Security\VirtualPatchRepository;

final class VirtualPatchAdmin
{
    public const PAGE_SLUG = 'shield-x-virtual-patches';

    /** @var VirtualPatchRepository */
    private $repository;

    public function __construct(?VirtualPatchRepository $repository = null)
    {
        $this->repository = $repository ?: new VirtualPatchRepository();
    }

    public function register(): void
    {
        add_action('admin_menu', [$this, 'registerMenu'], 40);
        add_action('admin_post_shieldx_virtual_patch_state', [$this, 'changeState']);
        add_action('admin_notices', [$this, 'notice']);
    }

    public function registerMenu(): void
    {
        // Register a hidden admin page. Threat Intelligence owns the only
        // navigation link, while WordPress still authorizes the page route.
        add_submenu_page(
            null,
            __('Virtual Patches', 'xerotact-shield-x-security'),
            __('Virtual Patches', 'xerotact-shield-x-security'),
            $this->capability(),
            self::PAGE_SLUG,
            [$this, 'render']
        );
    }

    public function render(): void
    {
        if (!current_user_can($this->capability())) {
            wp_die(esc_html__('You are not allowed to access this page.', 'xerotact-shield-x-security'));
        }
        $records = $this->repository->installedRecords();
        $catalog = $this->repository->catalogState();
        $feed = $catalog !== [] ? $catalog : $this->repository->feedState();
        $enforced = 0;
        foreach ($records as $record) {
            $state = is_array($record) ? (string) ($record['state'] ?? '') : '';
            if (in_array($state, ['challenge', 'block'], true)) {
                ++$enforced;
            }
        }
        $statusTone = $records === [] ? 'info' : 'good';
        $statusLabel = $records === []
            ? __('No patches', 'xerotact-shield-x-security')
            : ($enforced > 0
                ? __('Protection active', 'xerotact-shield-x-security')
                : __('Monitoring', 'xerotact-shield-x-security'));
        ?>
        <div class="wrap shieldx-admin shieldx-virtual-patches-page" data-shieldx-admin>
            <header class="shieldx-header">
                <div>
                    <span class="shieldx-kicker"><?php esc_html_e('Threat intelligence', 'xerotact-shield-x-security'); ?></span>
                    <h1 class="shieldx-title-row">
                        <span><?php esc_html_e('SHIELD-X Virtual Patches', 'xerotact-shield-x-security'); ?></span>
                        <span class="<?php echo esc_attr('shieldx-status-pill shieldx-status-pill--' . $statusTone); ?>">
                            <?php echo esc_html($statusLabel); ?>
                        </span>
                    </h1>
                    <p><?php esc_html_e('Verified threat definitions for components installed on this site enter monitor mode first. Challenge or block enforcement requires your confirmation.', 'xerotact-shield-x-security'); ?></p>
                </div>
                <div class="shieldx-header-meta">
                    <a class="shieldx-header-button shieldx-header-button--icon" href="<?php echo esc_url(admin_url('admin.php?page=shield-x-threat-intelligence')); ?>" title="<?php echo esc_attr__('Back to Threat Intelligence', 'xerotact-shield-x-security'); ?>">
                        <span class="dashicons dashicons-arrow-left-alt2" aria-hidden="true"></span>
                        <span class="shieldx-screen-reader-text"><?php esc_html_e('Back to Threat Intelligence', 'xerotact-shield-x-security'); ?></span>
                    </a>
                </div>
            </header>
            <div class="card" style="max-width:none">
                <h2><?php esc_html_e('Definition status', 'xerotact-shield-x-security'); ?></h2>
                <p>
                    <?php
                    echo esc_html(sprintf(
                        /* translators: 1: definition version, 2: sequence number, 3: verified date */
                        __('Version %1$s, sequence %2$d. Last verified: %3$s.', 'xerotact-shield-x-security'),
                        (string) ($feed['version'] ?? __('None', 'xerotact-shield-x-security')),
                        (int) ($feed['sequence'] ?? 0),
                        (string) ($feed['verified_at'] ?? __('Never', 'xerotact-shield-x-security'))
                    ));
                    ?>
                </p>
            </div>
            <table class="widefat striped" style="margin-top:16px">
                <thead><tr>
                    <th><?php esc_html_e('Patch', 'xerotact-shield-x-security'); ?></th>
                    <th><?php esc_html_e('Component', 'xerotact-shield-x-security'); ?></th>
                    <th><?php esc_html_e('State', 'xerotact-shield-x-security'); ?></th>
                    <th><?php esc_html_e('Expires', 'xerotact-shield-x-security'); ?></th>
                    <th><?php esc_html_e('Action', 'xerotact-shield-x-security'); ?></th>
                </tr></thead>
                <tbody>
                <?php if ($records === []) : ?>
                    <tr><td colspan="5"><?php esc_html_e('No verified virtual patches apply to components installed on this site.', 'xerotact-shield-x-security'); ?></td></tr>
                <?php else : ?>
                    <?php foreach ($records as $id => $record) :
                        $definition = isset($record['definition']) && is_array($record['definition']) ? $record['definition'] : [];
                        $component = isset($definition['component']) && is_array($definition['component']) ? $definition['component'] : [];
                        $state = (string) ($record['state'] ?? 'monitor');
                        ?>
                        <tr>
                            <td><strong><?php echo esc_html((string) ($definition['title'] ?? $id)); ?></strong><br><code><?php echo esc_html((string) $id); ?></code></td>
                            <td><?php echo esc_html((string) ($component['type'] ?? '') . ':' . (string) ($component['slug'] ?? '')); ?></td>
                            <td><?php echo esc_html($state); ?></td>
                            <td><?php echo esc_html((string) ($definition['expires_at'] ?? '')); ?></td>
                            <td><?php $this->renderActions((string) $id, $state); ?></td>
                        </tr>
                    <?php endforeach; ?>
                <?php endif; ?>
                </tbody>
            </table>
        </div>
        <?php
    }

    public function changeState(): void
    {
        if (!current_user_can($this->capability())) {
            wp_die(esc_html__('You are not allowed to perform this action.', 'xerotact-shield-x-security'));
        }
        check_admin_referer('shieldx_virtual_patch_state');
        $id = isset($_POST['patch_id']) ? sanitize_text_field(wp_unslash((string) $_POST['patch_id'])) : '';
        $state = isset($_POST['patch_state']) ? sanitize_key(wp_unslash((string) $_POST['patch_state'])) : '';
        $ok = $this->repository->setState($id, $state, get_current_user_id());
        if ($ok) {
            do_action('shieldx_audit_event', 'info', 'virtual_patch.state_changed', [
                'patch_id' => $id,
                'state' => $state,
                'user_id' => get_current_user_id(),
            ], ['time' => gmdate('c')]);
        }
        $redirectUrl = add_query_arg(
            [
                'shieldx_virtual_patch' => $ok ? 'updated' : 'blocked',
                '_wpnonce' => wp_create_nonce('shieldx_virtual_patch_notice'),
            ],
            admin_url('admin.php?page=' . self::PAGE_SLUG)
        );
        wp_safe_redirect($redirectUrl);
        exit;
    }

    public function notice(): void
    {
        $noticeNonce = isset($_GET['_wpnonce'])
            ? sanitize_text_field(wp_unslash((string) $_GET['_wpnonce']))
            : '';
        if (
            $noticeNonce !== ''
            && wp_verify_nonce($noticeNonce, 'shieldx_virtual_patch_notice') !== false
            && isset($_GET['shieldx_virtual_patch'])
        ) {
            $status = sanitize_key(wp_unslash((string) $_GET['shieldx_virtual_patch']));
            $class = $status === 'updated' ? 'notice notice-success is-dismissible' : 'notice notice-error is-dismissible';
            $message = $status === 'updated'
                ? __('The virtual patch state was updated.', 'xerotact-shield-x-security')
                : __('That patch cannot enter the requested state. It may be expired, revoked, fixed, or superseded.', 'xerotact-shield-x-security');
            echo '<div class="' . esc_attr($class) . '"><p>' . esc_html($message) . '</p></div>';
        }

        $screen = function_exists('get_current_screen') ? get_current_screen() : null;
        $screenId = is_object($screen) && isset($screen->id) ? (string) $screen->id : '';
        if ($screenId !== '' && strpos($screenId, 'shield-x') === false) {
            return;
        }
        $available = 0;
        foreach ($this->repository->installedRecords() as $record) {
            if (is_array($record) && (string) ($record['state'] ?? '') === 'monitor') {
                $available++;
            }
        }
        if ($available < 1) {
            return;
        }
        $url = admin_url('admin.php?page=shield-x-threat-intelligence');
        echo '<div class="notice notice-info"><p>'
            . esc_html(sprintf(
                /* translators: %d: number of monitored virtual patches */
                _n('%d verified virtual patch is monitoring traffic.', '%d verified virtual patches are monitoring traffic.', $available, 'xerotact-shield-x-security'),
                $available
            ))
            . ' <a href="' . esc_url($url) . '">' . esc_html__('Review in Threat Intelligence', 'xerotact-shield-x-security') . '</a></p></div>';
    }

    private function renderActions(string $id, string $state): void
    {
        if (in_array($state, ['revoked', 'expired-monitor', 'fixed-monitor', 'superseded'], true)) {
            esc_html_e('Enforcement unavailable', 'xerotact-shield-x-security');
            return;
        }
        foreach (['monitor' => __('Monitor', 'xerotact-shield-x-security'), 'challenge' => __('Challenge', 'xerotact-shield-x-security'), 'block' => __('Block', 'xerotact-shield-x-security'), 'disabled' => __('Disable', 'xerotact-shield-x-security')] as $target => $label) {
            if ($target === $state) {
                continue;
            }
            ?>
            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline-block;margin:0 4px 4px 0">
                <input type="hidden" name="action" value="shieldx_virtual_patch_state">
                <input type="hidden" name="patch_id" value="<?php echo esc_attr($id); ?>">
                <input type="hidden" name="patch_state" value="<?php echo esc_attr($target); ?>">
                <?php wp_nonce_field('shieldx_virtual_patch_state'); ?>
                <button type="submit" class="button<?php echo $target === 'block' ? ' button-primary' : ''; ?>"><?php echo esc_html($label); ?></button>
            </form>
            <?php
        }
    }

    private function capability(): string
    {
        return defined('SHIELDX_MANAGE_CAPABILITY') ? (string) SHIELDX_MANAGE_CAPABILITY : 'manage_options';
    }
}
