<?php

namespace WPSN\Modules\Privacy\Admin;

use WPSN\Core\Branding;
use WPSN\Core\Container;
use WPSN\Core\Capabilities;
use WPSN\Core\Settings;
use WPSN\Modules\Privacy\ExternalRequestLogRepository;

defined('ABSPATH') || exit;

final class PrivacyAdmin
{
    private const PAGE_SLUG = 'wpsn-privacy';

    private Container $container;
    private Settings $settings;

    private ?string $hookSuffix = null;

    public function __construct(Container $container)
    {
        $this->container = $container;
        $this->settings = $container->get('settings');
    }

    public function register(): void
    {
        add_action('admin_menu', [$this, 'addMenu']);
        add_action('admin_post_wpsn_privacy_clear_external_log', [$this, 'handleClearLog']);
    }

    public function addMenu(): void
    {
        $this->hookSuffix = add_management_page(
            __('SEO Privacy', 'wp-seo-next'),
            __('SEO Privacy', 'wp-seo-next'),
            Capabilities::CAP_TOOLS,
            self::PAGE_SLUG,
            [$this, 'render']
        );
    }

    private function currentView(): string
    {
        $view = isset($_GET['view']) ? sanitize_key((string) wp_unslash($_GET['view'])) : 'map';
        return in_array($view, ['map', 'log'], true) ? $view : 'map';
    }

    /**
     * @param array<string,string|int> $args
     */
    private function pageUrl(array $args = []): string
    {
        $base = admin_url('tools.php');
        $args = array_merge(['page' => self::PAGE_SLUG], $args);
        return (string) add_query_arg($args, $base);
    }

    private function redirectWithNotice(string $message, string $type = 'success', array $args = []): void
    {
        $url = $this->pageUrl(array_merge($args, [
            'wpsn_notice' => rawurlencode($message),
            'wpsn_notice_type' => $type,
        ]));
        wp_safe_redirect($url);
        exit;
    }

    public function handleClearLog(): void
    {
        if (!current_user_can(Capabilities::CAP_TOOLS)) {
            wp_die(esc_html__('You do not have permission to perform this action.', 'wp-seo-next'));
        }

        check_admin_referer('wpsn_privacy_clear_log', 'wpsn_nonce');

        $repo = new ExternalRequestLogRepository();
        $repo->deleteAll();

        $this->redirectWithNotice(__('External request log cleared.', 'wp-seo-next'), 'success', ['view' => 'log']);
    }

    public function render(): void
    {
        if (!current_user_can(Capabilities::CAP_TOOLS)) {
            wp_die(esc_html__('You do not have permission to access this page.', 'wp-seo-next'));
        }

        $view = $this->currentView();

        $notice = isset($_GET['wpsn_notice']) ? sanitize_text_field((string) wp_unslash($_GET['wpsn_notice'])) : '';
        $noticeType = isset($_GET['wpsn_notice_type']) ? sanitize_key((string) wp_unslash($_GET['wpsn_notice_type'])) : 'success';
        if (!in_array($noticeType, ['success', 'error', 'warning', 'info'], true)) {
            $noticeType = 'success';
        }

        $localOnly = (bool) $this->settings->get('privacy.local_only', false);
        $trustMode = (bool) $this->settings->get('privacy.trust_mode', false);

        echo '<div class="wrap">';
        echo '<h1>' . esc_html__('SEO Privacy', 'wp-seo-next') . '</h1>';
        echo '<p class="description">' . esc_html__('Transparency for outbound services + a local-only mode to disable external calls.', 'wp-seo-next') . '</p>';

        if ($notice !== '') {
            $class = 'notice-' . $noticeType;
            echo '<div class="notice ' . esc_attr($class) . ' is-dismissible"><p>' . esc_html($notice) . '</p></div>';
        }

        // Status summary.
        $statusText = $localOnly
            ? __('Local-only mode is ON: external services are blocked at runtime (stored configs are preserved).', 'wp-seo-next')
            : __('Local-only mode is OFF: external services may be used if enabled.', 'wp-seo-next');

        if ($trustMode) {
            echo '<div class="notice notice-info"><p>' . esc_html__('Trust Mode is enabled on this site. Privacy/security overrides are forced at runtime (local-only, hide AI UI, hide upgrade UI, disable install helpers).', 'wp-seo-next') . '</p></div>';
        }

        echo '<div class="notice ' . ($localOnly ? 'notice-warning' : 'notice-info') . '"><p>' . esc_html($statusText) . '</p>';
        echo '<p><a href="' . esc_url(admin_url('admin.php?page=wp-seo-next')) . '">' . esc_html__('Open Settings', 'wp-seo-next') . '</a></p>';
        echo '</div>';

        // Tabs.
        echo '<h2 class="nav-tab-wrapper" style="margin-top:10px;">';
        echo '<a href="' . esc_url($this->pageUrl(['view' => 'map'])) . '" class="nav-tab ' . ($view === 'map' ? 'nav-tab-active' : '') . '">' . esc_html__('Data map', 'wp-seo-next') . '</a>';
        echo '<a href="' . esc_url($this->pageUrl(['view' => 'log'])) . '" class="nav-tab ' . ($view === 'log' ? 'nav-tab-active' : '') . '">' . esc_html__('External request log', 'wp-seo-next') . '</a>';
        echo '</h2>';
        echo '<hr class="wp-header-end" />';

        if ($view === 'log') {
            $this->renderLog();
        } else {
            $this->renderDataMap();
        }

        echo '</div>';
    }

    private function renderDataMap(): void
    {
        $brand = Branding::brand($this->settings);
        $brandLabel = $brand !== '' ? $brand : __('This plugin', 'wp-seo-next');

        $services = $this->servicesCatalog();

        echo '<h2>' . esc_html__('Outbound services overview', 'wp-seo-next') . '</h2>';
        echo '<p class="description">' . esc_html__('This table documents where the plugin can send data when certain features are enabled.', 'wp-seo-next') . '</p>';

        echo '<table class="widefat striped" style="max-width: 1100px;">';
        echo '<thead><tr>';
        echo '<th>' . esc_html__('Service', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Used for', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Data sent', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Notes', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Status', 'wp-seo-next') . '</th>';
        echo '</tr></thead>';
        echo '<tbody>';

        foreach ($services as $key => $s) {
            $status = $this->serviceStatus($key);
            echo '<tr>';
            echo '<td><strong>' . esc_html($s['label']) . '</strong><br/><code style="opacity:.7">' . esc_html($key) . '</code></td>';
            echo '<td>' . wp_kses_post($s['used_for']) . '</td>';
            echo '<td>' . wp_kses_post($s['data_sent']) . '</td>';
            echo '<td>' . wp_kses_post($s['notes']) . '</td>';
            echo '<td>' . wp_kses_post($status) . '</td>';
            echo '</tr>';
        }

        echo '</tbody></table>';

        echo '<p class="description" style="margin-top:12px;">' . sprintf(
            /* translators: %s is plugin brand */
            esc_html__('%s does not transmit data unless you enable features that require external services (OpenAI / Google Search Console / IndexNow / Webhooks).', 'wp-seo-next'),
            esc_html($brandLabel)
        ) . '</p>';
    }

    private function renderLog(): void
    {
        $repo = new ExternalRequestLogRepository();

        $service = isset($_GET['service']) ? sanitize_key((string) wp_unslash($_GET['service'])) : '';
        $code = isset($_GET['code']) ? (int) $_GET['code'] : 0;

        $paged = isset($_GET['paged']) ? max(1, (int) $_GET['paged']) : 1;
        $perPage = 50;
        $offset = ($paged - 1) * $perPage;

        $filters = [];
        if ($service !== '') {
            $filters['service'] = $service;
        }
        if ($code > 0) {
            $filters['code'] = $code;
        }

        $total = $repo->count($filters);
        $rows = $repo->list($perPage, $offset, $filters);

        echo '<h2>' . esc_html__('External request log', 'wp-seo-next') . '</h2>';
        echo '<p class="description">' . esc_html__('Shows recent outbound HTTP requests made by this plugin (only marked requests are logged).', 'wp-seo-next') . '</p>';

        // Filters.
        echo '<form method="get" style="margin: 10px 0;">';
        echo '<input type="hidden" name="page" value="' . esc_attr(self::PAGE_SLUG) . '" />';
        echo '<input type="hidden" name="view" value="log" />';

        echo '<label style="margin-right:10px;">' . esc_html__('Service', 'wp-seo-next') . ': ';
        echo '<select name="service">';
        echo '<option value="">' . esc_html__('All', 'wp-seo-next') . '</option>';
        foreach (array_keys($this->servicesCatalog()) as $k) {
            echo '<option value="' . esc_attr($k) . '" ' . selected($service, $k, false) . '>' . esc_html($k) . '</option>';
        }
        echo '</select></label>';

        echo '<label style="margin-right:10px;">' . esc_html__('HTTP code', 'wp-seo-next') . ': ';
        echo '<input type="number" name="code" value="' . esc_attr($code > 0 ? (string) $code : '') . '" style="width:100px;" placeholder="200" />';
        echo '</label>';

        submit_button(__('Filter', 'wp-seo-next'), 'secondary', '', false);
        echo '</form>';

        // Clear log.
        echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" style="margin: 10px 0;">';
        echo '<input type="hidden" name="action" value="wpsn_privacy_clear_external_log" />';
        wp_nonce_field('wpsn_privacy_clear_log', 'wpsn_nonce');
        submit_button(__('Clear log', 'wp-seo-next'), 'delete', 'submit', false);
        echo '</form>';

        if (empty($rows)) {
            echo '<p>' . esc_html__('No log entries yet.', 'wp-seo-next') . '</p>';
            return;
        }

        echo '<table class="widefat striped" style="max-width: 1100px;">';
        echo '<thead><tr>';
        echo '<th>' . esc_html__('Time (UTC)', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Service', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Method', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('URL', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Code', 'wp-seo-next') . '</th>';
        echo '<th>' . esc_html__('Error', 'wp-seo-next') . '</th>';
        echo '</tr></thead><tbody>';

        foreach ($rows as $r) {
            $t = isset($r['created_at']) ? (string) $r['created_at'] : '';
            $svc = isset($r['service']) ? (string) $r['service'] : '';
            $m = isset($r['method']) ? (string) $r['method'] : '';
            $u = isset($r['url']) ? (string) $r['url'] : '';
            $c = isset($r['response_code']) ? (int) $r['response_code'] : 0;
            $e = isset($r['error']) ? (string) $r['error'] : '';

            if (strlen($u) > 80) {
                $uShort = substr($u, 0, 77) . '…';
            } else {
                $uShort = $u;
            }

            if (strlen($e) > 120) {
                $e = substr($e, 0, 117) . '…';
            }

            echo '<tr>';
            echo '<td><code>' . esc_html($t) . '</code></td>';
            echo '<td><code>' . esc_html($svc) . '</code></td>';
            echo '<td><code>' . esc_html($m) . '</code></td>';
            echo '<td><code title="' . esc_attr($u) . '">' . esc_html($uShort) . '</code></td>';
            echo '<td>' . esc_html((string) $c) . '</td>';
            echo '<td>' . esc_html($e) . '</td>';
            echo '</tr>';
        }

        echo '</tbody></table>';

        // Pagination.
        $totalPages = (int) ceil($total / $perPage);
        if ($totalPages > 1) {
            $links = paginate_links([
                'base' => add_query_arg(['paged' => '%#%'], $this->pageUrl(['view' => 'log', 'service' => $service, 'code' => $code > 0 ? (string) $code : ''])),
                'format' => '',
                'prev_text' => __('« Prev', 'wp-seo-next'),
                'next_text' => __('Next »', 'wp-seo-next'),
                'total' => $totalPages,
                'current' => $paged,
                'type' => 'plain',
            ]);
            if (is_string($links) && $links !== '') {
                echo '<div class="tablenav"><div class="tablenav-pages" style="margin: 12px 0;">' . wp_kses_post($links) . '</div></div>';
            }
        }
    }

    /**
     * @return array<string,array{label:string,used_for:string,data_sent:string,notes:string}>
     */
    private function servicesCatalog(): array
    {
        return [
            'openai' => [
                'label' => 'OpenAI',
                'used_for' => __('External AI generation (titles/descriptions/ALT drafts).', 'wp-seo-next'),
                'data_sent' => __('Prompt text may include post title, excerpt, selected parts of content (up to your max chars), and current SEO fields. Optionally redacted for emails/phones.', 'wp-seo-next'),
                'notes' => __('Controlled by Settings → AI. Can be blocked globally via Local-only mode.', 'wp-seo-next'),
            ],
            'gsc' => [
                'label' => __('Google Search Console', 'wp-seo-next'),
                'used_for' => __('Fetch queries/pages performance data and URL Inspection deep links.', 'wp-seo-next'),
                'data_sent' => __('OAuth tokens + selected property + requested date range/dimensions. URL Inspection sends the inspected URL.', 'wp-seo-next'),
                'notes' => __('Controlled by the Search Console module. Blocked by Local-only mode.', 'wp-seo-next'),
            ],
            'indexnow' => [
                'label' => 'IndexNow',
                'used_for' => __('Submit updated URLs for faster indexing.', 'wp-seo-next'),
                'data_sent' => __('List of URLs + IndexNow key (as per protocol).', 'wp-seo-next'),
                'notes' => __('Controlled by Tools → IndexNow and Settings → IndexNow. Blocked by Local-only mode.', 'wp-seo-next'),
            ],
            'sitemap_ping' => [
                'label' => __('Sitemap pings', 'wp-seo-next'),
                'used_for' => __('Ping search engines with sitemap URLs (optional).', 'wp-seo-next'),
                'data_sent' => __('Sitemap URL as a query parameter to ping endpoints.', 'wp-seo-next'),
                'notes' => __('Controlled by Tools → IndexNow (Sitemap pings). Blocked by Local-only mode.', 'wp-seo-next'),
            ],
            'webhook' => [
                'label' => __('Webhooks', 'wp-seo-next'),
                'used_for' => __('Automation: send events to your own endpoints (meta updated, redirects).', 'wp-seo-next'),
                'data_sent' => __('JSON payload: event name, timestamps, IDs, and relevant data (depends on webhook).', 'wp-seo-next'),
                'notes' => __('Controlled by Settings → Automation. Blocked by Local-only mode.', 'wp-seo-next'),
            ],
        ];
    }

    private function serviceStatus(string $key): string
    {
        $localOnly = (bool) $this->settings->get('privacy.local_only', false);
        if ($localOnly) {
            return '<span style="color:#a00; font-weight:600;">' . esc_html__('Blocked (Local-only)', 'wp-seo-next') . '</span>';
        }

        // Otherwise: show best-effort enabled/disabled status.
        if ($key === 'openai') {
            $enabled = (bool) $this->settings->get('ai.external.enabled', false);
            return $enabled
                ? '<span style="color:#0a7; font-weight:600;">' . esc_html__('Enabled', 'wp-seo-next') . '</span>'
                : '<span style="color:#666;">' . esc_html__('Disabled', 'wp-seo-next') . '</span>';
        }

        if ($key === 'gsc') {
            // Module toggle determines if UI is present; connection is shown on the GSC page.
            /** @var \WPSN\Core\ModuleRegistry $modules */
            $modules = $this->container->get('modules');
            $enabled = $modules->isEnabled('search_console');
            return $enabled
                ? '<span style="color:#0a7; font-weight:600;">' . esc_html__('Enabled (module)', 'wp-seo-next') . '</span>'
                : '<span style="color:#666;">' . esc_html__('Disabled (module)', 'wp-seo-next') . '</span>';
        }

        if ($key === 'indexnow') {
            $enabled = (bool) $this->settings->get('indexnow.enabled', false);
            return $enabled
                ? '<span style="color:#0a7; font-weight:600;">' . esc_html__('Enabled', 'wp-seo-next') . '</span>'
                : '<span style="color:#666;">' . esc_html__('Disabled', 'wp-seo-next') . '</span>';
        }

        if ($key === 'sitemap_ping') {
            $enabled = (bool) $this->settings->get('indexnow.sitemap_pings.enabled', false);
            return $enabled
                ? '<span style="color:#0a7; font-weight:600;">' . esc_html__('Enabled', 'wp-seo-next') . '</span>'
                : '<span style="color:#666;">' . esc_html__('Disabled', 'wp-seo-next') . '</span>';
        }

        if ($key === 'webhook') {
            $urls = $this->settings->get('automation.webhooks', []);
            $has = false;
            if (is_array($urls)) {
                foreach (['meta_updated','redirect_created','redirect_updated','audit_scan_completed','schema_scan_completed','schema_validation_failed'] as $k) {
                    $v = isset($urls[$k]) ? trim((string) $urls[$k]) : '';
                    if ($v !== '') {
                        $has = true;
                        break;
                    }
                }
            }
            return $has
                ? '<span style="color:#0a7; font-weight:600;">' . esc_html__('Configured', 'wp-seo-next') . '</span>'
                : '<span style="color:#666;">' . esc_html__('Not configured', 'wp-seo-next') . '</span>';
        }

        return '<span style="color:#666;">' . esc_html__('Unknown', 'wp-seo-next') . '</span>';
    }
}
