<?php

declare(strict_types=1);

namespace ShieldX\Core;

defined('ABSPATH') || exit;

use ShieldX\Scanner\ScheduledScanRunner;
use ShieldX\Maintenance\ScheduledBackupRunner;
use ShieldX\Maintenance\ScheduledRestorePointRunner;
use ShieldX\Security\Lockdown;
use ShieldX\Security\ReputationFeed;
use ShieldX\Security\UserProfiler;

final class Deactivator
{
    public static function deactivate(bool $networkWide = false): void
    {
        if ($networkWide && self::canIterateNetworkSites()) {
            self::forEachNetworkSite([self::class, 'deactivateCurrentSite']);
            return;
        }

        self::deactivateCurrentSite();
    }

    private static function deactivateCurrentSite(): void
    {
        // Deactivation must leave the host writable and remove only the
        // reversible Lockdown changes recorded in its signed manifest.
        try {
            Lockdown::fromWordPress()->revert(true, 'deactivated');
        } catch (\Throwable $error) {
            // A deactivation request must still complete if the host cannot
            // currently read the rollback manifest. Lockdown retains its own
            // diagnostic state for a later manual recovery attempt.
        }

        $addons = AddonRegistry::fromWordPress();
        $addons->dispatchLifecycle('shieldx_addon_deactivated');
        wp_clear_scheduled_hook('shieldx_hourly_maintenance');
        wp_clear_scheduled_hook('shieldx_temp_cleanup');
        wp_clear_scheduled_hook(SchedulerBridge::SELF_HEAL_ACTION);
        wp_clear_scheduled_hook(NotificationManager::DIGEST_CRON_HOOK);
        wp_clear_scheduled_hook(UserProfiler::CLEANUP_CRON_HOOK);
        ReputationFeed::clearScheduled();
        ScheduledScanRunner::clearScheduled();
        ScheduledBackupRunner::clearScheduled();
        ScheduledRestorePointRunner::clearScheduled();
    }

    private static function canIterateNetworkSites(): bool
    {
        return function_exists('is_multisite')
            && is_multisite()
            && function_exists('get_sites')
            && function_exists('switch_to_blog')
            && function_exists('restore_current_blog');
    }

    /**
     * @param callable():void $callback
     */
    private static function forEachNetworkSite(callable $callback): void
    {
        $siteIds = get_sites([
            'fields' => 'ids',
            'number' => 0,
        ]);
        if (!is_array($siteIds)) {
            $callback();
            return;
        }

        foreach ($siteIds as $siteId) {
            $siteId = (int) $siteId;
            if ($siteId <= 0) {
                continue;
            }

            switch_to_blog($siteId);
            try {
                RequestCache::clear();
                $callback();
            } finally {
                restore_current_blog();
                RequestCache::clear();
            }
        }
    }
}
