<?php
/**
 * SettingsPage — F201 (2026-07-30): redirect shim to Operator Dashboard Hub.
 *
 * Originally this page rendered the operator's SwapAds settings form
 * (server URL, license, audience comma-separated fields, auto-inject
 * toggle, default placement slug). It has been replaced by:
 *
 *   - License activation: stays here (handleRetryActivation still dispatches
 *     `swapads_client_retry_activation` for the legacy "Retry activation"
 *     button).
 *   - Auto-inject toggle: now lives in OperatorDashboardHubPage::renderSetupTab().
 *   - Audience fields (sub_niches / geo_buckets / traffic_ranges): now
 *     checkbox groups in OperatorDashboardHubPage::renderSetupTab(), fetched
 *     fresh from /v1/audience/definitions.
 *   - Server URL: removed (auto-discovered via HMAC key exchange).
 *   - Default placement slug: removed (always 'auto'; shortcode position
 *     determines actual placement).
 *
 * render() now redirects to the hub Setup tab for back-compat.
 *
 * @since 1.0.0
 */
declare(strict_types=1);

namespace SwapAds\Client\Admin;

use SwapAds\Client\License\FreemiusAutoActivator;
use SwapAds\Client\License\LicenseManager;
use SwapAds\Client\Http\Redirect;
use SwapAds\Client\Http\Request;

final class SettingsPage
{
    public const MENU_SLUG    = 'swapads-client';
    public const NONCE_ACTION = 'swapads_client_settings';

    /**
     * Register WP hooks.
     */
    public static function register(): void
    {
        add_action('admin_menu', [self::class, 'addMenu']);
        // F2XX-fix 2026-08-01: hide the sidebar link via CSS instead of
        // remove_submenu_page() (which broke the cap check in WP 7.0).
        add_action('admin_head', [self::class, 'hideSubmenuFromSidebar']);
        add_action('admin_post_swapads_client_save', [self::class, 'handleSave']);
    }

    /**
     * Register the admin menu (top-level). Kept so that any operators who
     * bookmark /wp-admin/admin.php?page=swapads-client still land on the
     * new hub Setup tab via the render() redirect below.
     */
    public static function addMenu(): void
        {
            // F2XX (2026-08-01): re-register the legacy swapads-client slug
            // as a HIDDEN submenu under the hub. The page itself just
            // redirects to the hub's Setup tab (see render()), but it must
            // be routable for old bookmarks + buttons that still link here.
            //
            // Previous behavior (F233): addMenu() was a no-op, which broke
            // the 'Edit Site Settings' button with 'Sorry, you are not
            // allowed to access this page' (WP refuses to route to an
            // unregistered page slug).
            add_submenu_page(
                OperatorDashboardHubPage::MENU_SLUG,
                'Site Settings',
                'Site Settings',
                'manage_options',
                self::MENU_SLUG,
                [self::class, 'render']
            );
            // Immediately remove from sidebar so the visible submenu count
            // stays at 4 (operator spec). Keep the URL routable.
            // F2XX-fix 2026-08-01: do NOT call remove_submenu_page() — it breaks
        // admin-post.php routing in WP 7.0. Sidebar link is hidden via
        // admin_head CSS (see hideSubmenuFromSidebar).
        }

    /**
     * Render the settings page.
     *
     * F201 (2026-07-30): settings have moved into the Operator Dashboard Hub's
     * "Setup" tab (`?page=swapads-client-operator-hub&tab=setup`). This render()
     * now redirects there for back-compat. Operators who bookmark the old
     * `?page=swapads-client` URL land on the new Setup tab automatically.
     */
    public static function render(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die('Insufficient permissions', 'Forbidden', ['response' => 403]);
        }
        $dest = add_query_arg(
            ['page' => OperatorDashboardHubPage::MENU_SLUG, 'tab' => OperatorDashboardHubPage::TAB_SETUP],
            admin_url('admin.php')
        );
        // No exit; here so the function returns normally after the
        // redirect header is sent. WP itself calls exit but that's only
        // safe in a real request — tests want to assert on the URL.
        Redirect::to($dest, 302);
    }

    /**
     * Handle the Save Settings POST.
     *
     * F201 (2026-07-30): only auto_inject + license activation remain
     * here. Everything else moved to OperatorDashboardHubPage::handleSaveAudience()
     * (Setup tab).
     */
    public static function handleSave(): void
    {
        if (!current_user_can('manage_options')) {
            return;
        }
        check_admin_referer(self::NONCE_ACTION);
        if (!LicenseManager::isLicensed()) {
            $key    = Request::input('license_key', '', 'post');
            $secret = Request::input('license_secret', '', 'post');
            if ($key !== '' && $secret !== '') {
                // Activate via server (lightweight call)
                LicenseManager::store($key, $secret, 0, wp_parse_url(home_url(), PHP_URL_HOST) ?: '', 'pending');
            }
        }
        // F201 (2026-07-30): niche/sub-niche/geo/traffic ranges + default_placement
        // removed from this handler. Those fields now live in
        // OperatorDashboardHubPage::handleSaveAudience() (Setup tab).
        update_option('swapads_client_auto_inject', Request::inputBool('auto_inject', false, 'post') ? 1 : 0);
        // F2XX (2026-08-01): Redirect::to() handles the SWAPADS_TESTING_REDIRECT_EXIT
        // guard internally so the test bootstrap can capture the redirect URL.
        // Bug 4 from operator feedback 2026-08-01: 'edit site settings still doesn't work'.
        Redirect::to(add_query_arg(
            ['page' => OperatorDashboardHubPage::MENU_SLUG, 'tab' => OperatorDashboardHubPage::TAB_SETUP, 'saved' => '1'],
            admin_url('admin.php')
        ));
    }

    /**
     * CF17: admin-post handler for the 'Retry activation' button.
     *
     * Clears the cached activation state and re-runs immediately.
     * Redirects back to settings with retry=ok / retry=fail query arg.
     */
    public static function handleRetryActivation(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die('Insufficient permissions', 'Forbidden', ['response' => 403]);
        }
        check_admin_referer('swapads_client_retry_activation');

        try {
            $result = FreemiusAutoActivator::retryNow();
            $ok = is_array($result) && !empty($result['success']);
        } catch (\Throwable) {
            $ok = false;
        }

        $redirect = add_query_arg(
            ['page' => self::MENU_SLUG, 'retry' => $ok ? 'ok' : 'fail'],
            admin_url('admin.php')
        );
        // F2XX (2026-08-01): Redirect::to() handles the SWAPADS_TESTING_REDIRECT_EXIT
        // guard internally (see Bug 4 fix in handleSave above).
        Redirect::to($redirect);
    }


    /**
     * Hide the sidebar link via CSS instead of remove_submenu_page().
     *
     * F2XX-fix 2026-08-01: WP 7.0's user_can_access_admin_page() iterates
     * $submenu[$parent] looking for the slug; if remove_submenu_page() removed
     * the entry, the cap check returned false and the operator saw
     * 'Sorry, you are not allowed to access this page' on form postbacks.
     *
     * Keeping the entry in $submenu (so the cap check passes) and hiding the
     * visual link via CSS is the correct WP 7.0 pattern.
     */
    public static function hideSubmenuFromSidebar(): void
    {
        echo '<style>#adminmenu a[href*="page=swapads-client-settings"]{display:none!important}</style>';
    }
}
