<?php

/**
 * LolaCore — Hub Transparency Page
 *
 * @package LolaCore
 * @license GPL-2.0-or-later
 */

declare(strict_types=1);

namespace LolaCore\Hub;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * wp-admin transparency panel for the site owner (sprint C2 / E5).
 */
final class HubTransparencyPage
{
    public const MENU_SLUG = 'lolacore-agency-connection';

    public function __construct(
        private ?PairingRegistrar $pairing = null,
        private ?HubScope $scope = null,
        private ?HubActionLogReader $logReader = null,
        private ?HubMemoryTransparency $memory = null,
        private ?HubRevocationService $revocation = null,
        private ?HubAbilityDomainMapper $domainMapper = null,
    ) {
        $this->pairing      = $pairing ?? new PairingRegistrar();
        $this->scope        = $scope ?? new HubScope();
        $this->logReader    = $logReader ?? new HubActionLogReader();
        $this->memory       = $memory ?? new HubMemoryTransparency();
        $this->revocation   = $revocation ?? new HubRevocationService($this->pairing, $this->scope, $this->memory);
        $this->domainMapper = $domainMapper ?? new HubAbilityDomainMapper();
    }

    public function register(): void
    {
        \add_action('admin_menu', [$this, 'registerMenu'], 20);
        \add_action('admin_post_lolacore_hub_save_scope', [$this, 'handleSaveScope']);
        \add_action('admin_post_lolacore_hub_disconnect', [$this, 'handleDisconnect']);
        \add_action('admin_post_lolacore_hub_forget_memory', [$this, 'handleForgetMemory']);
    }

    public function registerMenu(): void
    {
        \add_submenu_page(
            'lolacore',
            \__('Agency Connection', 'lolacore'),
            \__('Agency Connection', 'lolacore'),
            'manage_options',
            self::MENU_SLUG,
            [$this, 'renderPage']
        );
    }

    public function renderPage(): void
    {
        if (!\current_user_can('manage_options')) {
            \wp_die(\esc_html__('You do not have sufficient permissions to access this page.', 'lolacore'));
        }

        $connection = $this->pairing->getConnectionState();
        $connected  = $this->pairing->isConnected();
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only log search; no state change.
        $search     = isset($_GET['hub_log_search']) ? \sanitize_text_field((string) wp_unslash($_GET['hub_log_search'])) : '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only pagination; no state change.
        $page       = isset($_GET['hub_log_page']) ? max(1, (int) $_GET['hub_log_page']) : 1;
        $log        = $this->logReader->getEntries($page, 20, $search);
        $reconcile  = $this->memory->getLastReconcile();
        $domains       = $this->domainMapper->getSelectableDomains();
        $denied        = $this->scope->getDeniedDomains();
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Flash notice from redirect; display only.
        $notice        = isset($_GET['hub_notice']) ? \sanitize_key((string) $_GET['hub_notice']) : '';
        $scope         = $this->scope;
        $allowedLabels = $this->scope->getAllowedDomainLabels();

        $template = \plugin_dir_path(dirname(__DIR__)) . 'templates/hub-transparency-page.php';
        if (!\file_exists($template)) {
            echo '<div class="wrap"><p>' . \esc_html__('Transparency template not found.', 'lolacore') . '</p></div>';
            return;
        }

        require $template;
    }

    public function handleSaveScope(): void
    {
        $this->verifyPost('lolacore_hub_save_scope');

        $allowed = $this->allowedDomainsFromPost();

        $selectable = array_keys($this->domainMapper->getSelectableDomains());
        $denied     = array_values(array_diff($selectable, $allowed));

        $this->scope->setDeniedDomains($denied);

        $this->redirectWithNotice('scope_saved');
    }

    public function handleDisconnect(): void
    {
        $this->verifyPost('lolacore_hub_disconnect');

        $this->revocation->disconnect();

        $this->redirectWithNotice('disconnected');
    }

    public function handleForgetMemory(): void
    {
        $this->verifyPost('lolacore_hub_forget_memory');

        $this->memory->forgetOperatorFacts();

        $this->redirectWithNotice('memory_forgotten');
    }

    private function verifyPost(string $action): void
    {
        if (!\current_user_can('manage_options')) {
            \wp_die(\esc_html__('You do not have sufficient permissions.', 'lolacore'));
        }

        $nonce = isset($_POST['_wpnonce'])
            ? \sanitize_text_field((string) wp_unslash($_POST['_wpnonce']))
            : '';
        if (!\wp_verify_nonce($nonce, $action)) {
            \wp_die(\esc_html__('Security check failed.', 'lolacore'));
        }
    }

    /**
     * @return string[]
     */
    private function allowedDomainsFromPost(): array
    {
        if (! isset($_POST['hub_allowed_domains']) || ! is_array($_POST['hub_allowed_domains'])) {
            return [];
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Only called after verifyPost(); values sanitized below.
        $raw = wp_unslash($_POST['hub_allowed_domains']);

        return array_map(static fn($v): string => \sanitize_key((string) $v), $raw);
    }

    private function redirectWithNotice(string $notice): void
    {
        $url = \add_query_arg(
            [
                'page'       => self::MENU_SLUG,
                'hub_notice' => $notice,
            ],
            \admin_url('admin.php')
        );

        \wp_safe_redirect($url);
        exit;
    }
}
