<?php

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

class AIEO_Panel_Manifest {

    const SCHEMA = 1;

    
    public static function register() {
        foreach (array(
            'update_option_aieo_push_engine_status',
            'add_option_aieo_push_engine_status',
            'update_option_aieo_push_vapid',
            'add_option_aieo_push_vapid',
            'update_option_aieo_dmm_settings',      
            'update_option_aieo_seo_redirects_ver', 
            'update_option_aieo_push_banner_settings',
            'aieo_seo_edge_exported',               
            'update_option_aieo_seo_sitemap_built_at', 
            'add_option_aieo_seo_sitemap_built_at',
        ) as $hook) {
            add_action($hook, array(__CLASS__, 'request_write'), 20);
        }
    }

    
    public static function request_write() {
        static $scheduled = false;
        if ($scheduled) { return; }
        $scheduled = true;
        add_action('shutdown', array(__CLASS__, 'write'), 99);
    }

    public static function panel_dir() {
        $up = wp_upload_dir();
        return trailingslashit($up['basedir']) . 'aieo-panel';
    }

    
    public static function write() {
        $dir = self::panel_dir();
        if (!wp_mkdir_p($dir)) { return false; }
        $json = wp_json_encode(self::build(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        if ($json === false) { return false; }
        return self::write_atomic($dir . '/manifest.json', $json);
    }

    public static function build() {
        return array(
            'schema'       => self::SCHEMA,
            'generated_at' => time(),
            'plugin'       => array(
                'core_version'   => defined('AIEO_VERSION') ? (string) AIEO_VERSION : '',
                'runtime_active' => defined('AIEO_RUNTIME_VERSION'),
            ),
            'tier'         => self::tier_block(),
            'site'         => array(
                'is_ssl'           => self::site_is_ssl(),
                'wp_cron_disabled' => (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON),
                'timezone'         => function_exists('wp_timezone_string') ? wp_timezone_string() : (string) get_option('timezone_string'),
            ),
            'features'     => array(
                'push' => self::push_block(),
                'edge' => self::edge_block(),
            ),
        );
    }

    
    public static function site_is_ssl() {
        return 'https' === strtolower((string) wp_parse_url(home_url('/'), PHP_URL_SCHEME));
    }

    private static function tier_block() {
        $membership_pro = (get_option('aieo_user_membership') === 'Pro');
        $rooster        = (get_option('aieo_rooster_status') === 'connected');
        return array(
            'name'   => ($membership_pro || $rooster) ? 'pro' : 'free',
            'method' => $rooster ? 'hub' : ($membership_pro ? 'membership' : 'none'),
        );
    }

    private static function push_block() {
        global $wpdb;
        $vapid  = get_option('aieo_push_vapid', array());
        $vpub   = (is_array($vapid) && !empty($vapid['public_b64url'])) ? (string) $vapid['public_b64url'] : '';
        $subs_t = $wpdb->prefix . 'aieo_push_subscriptions';
        $schema = ((string) $wpdb->get_var("SHOW TABLES LIKE '{$subs_t}'") === $subs_t);
        $count  = $schema ? (int) $wpdb->get_var("SELECT COUNT(*) FROM {$subs_t} WHERE status = 'active'") : 0;
        $engine = (get_option('aieo_push_engine_status', 'live') === 'paused') ? 'paused' : 'live';
        $banner = get_option('aieo_push_banner_settings', array());
        $banner_on = !is_array($banner) || !isset($banner['banner_enabled']) || !empty($banner['banner_enabled']);
        $block = array(
            'enabled'            => (bool) $banner_on,
            'ready'              => (bool) (self::site_is_ssl() && $vpub !== '' && $schema && defined('AIEO_RUNTIME_VERSION')),
            'tier_required'      => 'pro',
            'engine_status'      => $engine,
            'vapid_public_key'   => $vpub,
            'service_worker'     => array('path' => '/aieo-push-sw.js', 'scope' => '/'),
            'subscription_count' => $count,
            'nginx_requirement'  => array(
                'location' => '/aieo-push-sw.js',
                'block'    => "location = /aieo-push-sw.js {\n    try_files /nonexistent /index.php?aieo_push_sw=1;\n}",
            ),
        );
        $block['hash'] = 'sha1:' . sha1(wp_json_encode($block));
        return $block;
    }

    private static function edge_block() {
        
        
        
        
        
        
        $up_base  = trailingslashit(wp_upload_dir()['basedir']);
        $edge_dir = $up_base . 'aieo-redirects/';
        $settings = get_option('aieo_dmm_settings', array());
        $seo_on   = is_array($settings) && !empty($settings['seo']['enabled']);

        $ver_file = $edge_dir . 'version.txt';
        $ver = is_readable($ver_file) ? trim((string) file_get_contents($ver_file)) : '';
        if ($ver === '') { $ver = (string) get_option('aieo_seo_redirects_ver', '0'); }

        $counts = array();
        foreach (array('301', '302', '307', '308', '410') as $code) {
            $counts[$code] = self::count_map_lines($edge_dir . $code . '.map');
        }

        return array(
            'enabled'           => (bool) $seo_on,
            'redirects_version' => $ver,
            'redirect_counts'   => $counts,
            'sitemap_present'   => is_readable($up_base . 'aieo-sitemaps/sitemap.xml'),
        );
    }

    
    private static function count_map_lines($path) {
        if (!is_readable($path)) { return 0; }
        $fh = @fopen($path, 'r');
        if (!$fh) { return 0; }
        $n = 0;
        while (($line = fgets($fh)) !== false) {
            $t = ltrim($line);
            if ($t === '' || $t[0] === '#') { continue; }
            $n++;
        }
        fclose($fh);
        return $n;
    }

    
    private static function write_atomic($path, $contents) {
        $tmp = $path . '.' . wp_generate_password(6, false, false) . '.tmp';
        if (file_put_contents($tmp, $contents) === false) { return false; }
        if (!@rename($tmp, $path)) { @unlink($tmp); return false; }
        return true;
    }
}

if (!function_exists('aieo_panel_manifest_activate')) {
    function aieo_panel_manifest_activate() {
        add_option('aieo_push_engine_status', 'paused');
        if (class_exists('AIEO_Panel_Manifest')) {
            AIEO_Panel_Manifest::write();
        }
    }
}

if (defined('WP_CLI') && WP_CLI) {

    class AIEO_CLI_Push {

        
        public function prepare($args, $assoc_args) {
            
            $schema_php = AIEO_DIR . 'includes/dmm/sql/push-schema.php';
            if (file_exists($schema_php)) { require_once $schema_php; }
            if (function_exists('aieo_push_install_schema')) { aieo_push_install_schema(); }

            
            $vpub = '';
            if (class_exists('AIEO_Push_Sender') && method_exists('AIEO_Push_Sender', 'instance')) {
                $keys = AIEO_Push_Sender::instance()->get_keys();
                if (is_array($keys) && !empty($keys['public_b64url'])) { $vpub = (string) $keys['public_b64url']; }
            }

            
            flush_rewrite_rules(false);

            
            if (class_exists('AIEO_Panel_Manifest')) { AIEO_Panel_Manifest::write(); }

            \WP_CLI::line(wp_json_encode(array(
                'vapid_public_key' => $vpub,
                'sw_path'          => '/aieo-push-sw.js',
                'scope'            => '/',
            )));
        }

        
        public function verify_readiness($args, $assoc_args) {
            global $wpdb;
            $subs_t = $wpdb->prefix . 'aieo_push_subscriptions';
            $vapid  = get_option('aieo_push_vapid', array());
            \WP_CLI::line(wp_json_encode(array(
                'php_openssl' => extension_loaded('openssl'),
                'https'       => AIEO_Panel_Manifest::site_is_ssl(),
                'wp_cron'     => !(defined('DISABLE_WP_CRON') && DISABLE_WP_CRON),
                'schema'      => ((string) $wpdb->get_var("SHOW TABLES LIKE '{$subs_t}'") === $subs_t),
                'runtime'     => defined('AIEO_RUNTIME_VERSION'),
                'vapid'       => (is_array($vapid) && !empty($vapid['public_b64url'])),
            )));
        }

        
        public function status($args, $assoc_args) {
            global $wpdb;
            $subs_t = $wpdb->prefix . 'aieo_push_subscriptions';
            $schema = ((string) $wpdb->get_var("SHOW TABLES LIKE '{$subs_t}'") === $subs_t);
            $count  = $schema ? (int) $wpdb->get_var("SELECT COUNT(*) FROM {$subs_t} WHERE status = 'active'") : 0;
            $vapid  = get_option('aieo_push_vapid', array());
            $vpub   = (is_array($vapid) && !empty($vapid['public_b64url'])) ? (string) $vapid['public_b64url'] : '';
            $engine = (get_option('aieo_push_engine_status', 'live') === 'paused') ? 'paused' : 'live';
            \WP_CLI::line(wp_json_encode(array(
                'installed'          => $schema,
                'ready'              => (bool) (AIEO_Panel_Manifest::site_is_ssl() && $vpub !== '' && $schema && defined('AIEO_RUNTIME_VERSION')),
                'engine_status'      => $engine,
                'subscription_count' => $count,
                'vapid_public_key'   => $vpub,
                'service_worker'     => array('path' => '/aieo-push-sw.js', 'scope' => '/'),
                'tier_required'      => 'pro',
            )));
        }

        
        public function set_engine($args, $assoc_args) {
            $state = isset($args[0]) ? strtolower((string) $args[0]) : '';
            if (!in_array($state, array('live', 'paused'), true)) {
                \WP_CLI::line(wp_json_encode(array('ok' => false, 'error' => 'state must be "live" or "paused"')));
                \WP_CLI::halt(1);
            }
            if (class_exists('AIEO_DMM_Web_Push') && method_exists('AIEO_DMM_Web_Push', 'set_engine_status')) {
                AIEO_DMM_Web_Push::set_engine_status($state); 
            } else {
                update_option('aieo_push_engine_status', $state); 
            }
            if (class_exists('AIEO_Panel_Manifest')) { AIEO_Panel_Manifest::write(); } 
            \WP_CLI::line(wp_json_encode(array('ok' => true, 'engine_status' => $state)));
        }
    }

    \WP_CLI::add_command('aieo push', 'AIEO_CLI_Push');
}
