<?php

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

class VS_Modules {

    const OPTION_KEY = 'vs_modules';

    /* =========================================================
       Module registry
    ========================================================= */

    
    public static function get_registry(): array {
        return [

            /* ── Free modules ─────────────────────────────────── */
           

            'export_import' => [
                'name'    => __( 'Export / Import', 'vendor-space' ),
                'desc'    => __( 'Bulk export and import products, orders, and vendor data via CSV.', 'vendor-space' ),
                'icon'    => 'M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12',
                'color'   => 'green',
                'type'    => 'free',
                'default' => true,
            ],

          

           
         
           

             /* ── Pro modules ──────────────────────────────────── */
            'live_chat' => [
                'name'    => __( 'Live Chat', 'vendor-space' ),
                'desc'    => __( 'Real-time messaging between vendors and their customers.', 'vendor-space' ),
                'icon'    => 'M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z',
                'color'   => 'purple',
                'type'    => 'pro',
                'default'     => false,
                'price'       => 29.99,
                'class'       => 'VS_Pro_LiveChat',

                'default' => false,
            ],
             'vendor_ads' => [
                'name'        => __( 'Vendor Ads', 'vendor-space' ),
                'desc'        => __( 'Let vendors promote their products with paid ad campaigns.', 'vendor-space' ),
                'icon'        => 'M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z',
                'color'       => 'blue',
                'type'        => 'pro',
                'default'     => false,
                'price'       => 29.99,
                'class'       => 'VS_Ads',
            ],

        ];
    }

    /* =========================================================
       Active-state helpers
    ========================================================= */

    public static function get_active(): array {
        $saved = get_option( self::OPTION_KEY, null );

        // First-run: build defaults from registry.
        if ( ! is_array( $saved ) ) {
            $saved = [];
            foreach ( self::get_registry() as $id => $mod ) { // id : name of module , mod : data of module
                $saved[ $id ] = ! empty( $mod['default'] ); //If true → returns true; if empty or false → returns false
            }
            update_option( self::OPTION_KEY, $saved );
        }

        return $saved;
    }

    public static function is_active( string $module_id ): bool {
        $active = self::get_active();
        return ! empty( $active[ $module_id ] );
    }

    public static function get_purchased(): array {
        return get_option( 'vs_purchased_modules', [] );
    }

    public static function is_purchased( string $module_id ): bool {
        $registry = self::get_registry();
        if ( ! isset( $registry[ $module_id ] ) ) {
            return false;
        }
        // Free modules are always purchased.
        if ( $registry[ $module_id ]['type'] === 'free' ) {
            return true;
        }
        $purchased = self::get_purchased();
        return ! empty( $purchased[ $module_id ] );
    }

    /* =========================================================
       Initialise active modules
    ========================================================= */

    public static function init(): void {
       

        // Register AJAX handlers first (before we boot modules).
        add_action( 'wp_ajax_vs_toggle_module', [ __CLASS__, 'ajax_toggle' ] );
        add_action( 'wp_ajax_vs_purchase_module', [ __CLASS__, 'ajax_purchase' ] );
        add_action( 'wp_ajax_vs_create_payment_intent', [ __CLASS__, 'ajax_create_payment_intent' ] );

        $active  = self::get_active();
        $registry = self::get_registry();

        foreach ( $active as $id => $enabled ) {
            if ( ! $enabled ) {
                continue;
            }
            if ( ! isset( $registry[ $id ] ) ) {
                continue;
            }
            $mod = $registry[ $id ];

            // Load primary file + class.
            if ( ! empty( $mod['file'] ) ) {
                $path = VS_PATH . $mod['file'];
                if ( file_exists( $path ) ) {
                    require_once $path;
                }
            }
            if ( ! empty( $mod['class'] ) && class_exists( $mod['class'] ) ) {
                call_user_func( [ $mod['class'], 'init' ] );
            }

            // Load extra companion files (e.g. ads-admin, ads-frontend).
            if ( ! empty( $mod['extra_files'] ) ) {
                foreach ( $mod['extra_files'] as $rel_path => $class_name ) {
                    $path = VS_PATH . $rel_path;
                    if ( file_exists( $path ) ) {
                        require_once $path;
                    }
                    if ( class_exists( $class_name ) && method_exists( $class_name, 'init' ) ) {
                        call_user_func( [ $class_name, 'init' ] );
                    }
                }
            }
        }
    }

    /* =========================================================
       AJAX: toggle a single module on / off
    ========================================================= */

    public static function ajax_toggle(): void {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => __( 'Permission denied.', 'vendor-space' ) ] );
        }
        check_ajax_referer( 'vs_modules_nonce', 'nonce' );

        $id      = sanitize_key( (string) ( $_POST['module'] ?? '' ) );
        $enabled = rest_sanitize_boolean( $_POST['enabled'] ?? false );

        $registry = self::get_registry();
        if ( ! isset( $registry[ $id ] ) ) {
            wp_send_json_error( [ 'message' => __( 'Unknown module.', 'vendor-space' ) ] );
        }

       

        $active       = self::get_active();
        $active[ $id ] = (bool) $enabled;
        update_option( self::OPTION_KEY, $active );

        wp_send_json_success( [
            'message' => $enabled
                ? __( 'Module activated.', 'vendor-space' )
                : __( 'Module deactivated.', 'vendor-space' ),
            'active'  => (bool) $enabled,
        ] );
    }

    public static function ajax_purchase(): void {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => __( 'Permission denied.', 'vendor-space' ) ] );
        }
        check_ajax_referer( 'vs_modules_nonce', 'nonce' );

        $id = sanitize_key( (string) ( $_POST['module'] ?? '' ) );
        
        $registry = self::get_registry();
        if ( ! isset( $registry[ $id ] ) ) {
            wp_send_json_error( [ 'message' => __( 'Unknown module.', 'vendor-space' ) ] );
        }


        $purchased = self::get_purchased();
        $purchased[ $id ] = true;
        update_option( 'vs_purchased_modules', $purchased );

        wp_send_json_success( [
            'message' => sprintf( __( '%s purchased successfully!', 'vendor-space' ), $registry[ $id ]['name'] ),
        ] );
    }

    public static function ajax_create_payment_intent(): void {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => __( 'Permission denied.', 'vendor-space' ) ] );
        }
        check_ajax_referer( 'vs_modules_nonce', 'nonce' );

        $id = sanitize_key( (string) ( $_POST['module'] ?? '' ) );
        $registry = self::get_registry();
        if ( ! isset( $registry[ $id ] ) ) {
            wp_send_json_error( [ 'message' => __( 'Unknown module.', 'vendor-space' ) ] );
        }

        $secret_key = VS_Admin_Settings::get_option('payments', 'stripe_secret_key');
        if ( ! $secret_key ) {
            wp_send_json_error( [ 'message' => __( 'Stripe secret key missing.', 'vendor-space' ) ] );
        }

        $amount = round( ( $registry[ $id ]['price'] ?? 0 ) * 100 ); // in cents
        
        $response = wp_remote_post( 'https://api.stripe.com/v1/payment_intents', [
            'headers' => [
                'Authorization' => 'Bearer ' . $secret_key,
                'Content-Type'  => 'application/x-www-form-urlencoded',
            ],
            'body' => [
                'amount'   => $amount,
                'currency' => strtolower( VS_Admin_Settings::get_option('general', 'currency', 'USD') ),
                'metadata' => [
                    'module' => $id,
                    'site_url' => get_site_url(),
                ],
            ],
        ]);

        if ( is_wp_error( $response ) ) {
            wp_send_json_error( [ 'message' => $response->get_error_message() ] );
        }

        $body = json_decode( wp_remote_retrieve_body( $response ), true );
        if ( ! empty( $body['error'] ) ) {
            wp_send_json_error( [ 'message' => $body['error']['message'] ] );
        }

        wp_send_json_success( [
            'client_secret' => $body['client_secret']
        ] );
    }

    /* =========================================================
       Render – admin dashboard tab
       Call from VS_Admin_Settings or directly inside a tab div.
    ========================================================= */

    public static function render_front_tab(): string {
        if ( ! current_user_can( 'manage_options' ) ) {
            return '<div class="vs-alert vs-alert-error">' . esc_html__( 'Access denied.', 'vendor-space' ) . '</div>';
        }
        ob_start();
        echo '<div class="vs-tab" id="tab-modules" style="display:none;">';
        self::render();
        echo '</div>';
        return ob_get_clean();
    }

    public static function render(): void {
        if ( ! current_user_can( 'manage_options' ) ) {
            echo '<div class="vs-alert vs-alert-error">' . esc_html__( 'Access denied.', 'vendor-space' ) . '</div>';
            return;
        }

        $registry = self::get_registry();
        $active   = self::get_active();
        $nonce    = wp_create_nonce( 'vs_modules_nonce' );

        /* colour map → Tailwind-compatible inline palette */
        $colors = [
            'blue'   => [ 'bg' => '#e6f1fb', 'icon' => '#185fa5' ],
            'green'  => [ 'bg' => '#eaf3de', 'icon' => '#3b6d11' ],
            'teal'   => [ 'bg' => '#e1f5ee', 'icon' => '#0f6e56' ],
            'amber'  => [ 'bg' => '#faeeda', 'icon' => '#854f0b' ],
            'coral'  => [ 'bg' => '#faece7', 'icon' => '#993c1d' ],
            'purple' => [ 'bg' => '#eeedfe', 'icon' => '#534ab7' ],
            'pink'   => [ 'bg' => '#fbeaf0', 'icon' => '#993556' ],
            'gray'   => [ 'bg' => '#f1efe8', 'icon' => '#5f5e5a' ],
        ];

        include_once ABSPATH . 'wp-admin/includes/plugin.php';
        $pro_plugin_path = 'vendor space pro/vendor-space.php';
        $is_pro_active   = is_plugin_active( $pro_plugin_path );
        $is_pro_installed = file_exists( WP_PLUGIN_DIR . '/' . $pro_plugin_path );
        ?>

        <style>
            .vsm-card-footer {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 16px;
                border-top: 1px solid #f1f5f9;
                background: #f8fafc;
                min-height: 70px;
            }

            /* Pro Action Buttons */
            .vsm-pro-action-wrap {
                width: 100%;
                display: flex;
                justify-content: center;
            }

            .vsm-activate-pro-btn {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                gap: 8px;
                padding: 10px 20px;
                border-radius: 12px;
                text-decoration: none;
                font-size: 13.5px;
                font-weight: 700;
                color: #ffffff;
                background: linear-gradient(135deg, #6366f1, #8b5cf6);
                box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);
                transition: all 0.2s ease;
                border: none;
            }

            .vsm-activate-pro-btn:hover {
                transform: translateY(-1px);
                box-shadow: 0 6px 15px rgba(99, 102, 241, 0.3);
                color: #fff;
            }

            .vsm-buy-btn {
                display: inline-flex;
                align-items: center;
                gap: 8px;
                padding: 10px 20px;
                background: #fff;
                color: #4f46e5;
                font-size: 13.5px;
                font-weight: 700;
                border: 2px solid #e2e8f0;
                border-radius: 12px;
                text-decoration: none;
                transition: all 0.2s ease;
            }

            .vsm-buy-btn:hover {
                background: #f5f3ff;
                border-color: #c7d2fe;
                color: #4338ca;
            }

            .vsm-lock {
                color: #94a3b8;
                font-size: 14px;
            }

            .vsm-settings-btn {
                font-size: 13px;
                font-weight: 600;
                color: #6366f1;
                text-decoration: none;
                padding: 6px 12px;
                border-radius: 8px;
                background: #eef2ff;
                transition: 0.2s;
            }

            .vsm-settings-btn:hover {
                background: #e0e7ff;
            }
        </style>

        <div class="vsm-wrap" id="vs-modules-app"
             data-ajax="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>"
             data-nonce="<?php echo esc_attr( $nonce ); ?>"
             <?php if ( ($stripe_key = VS_Admin_Settings::get_option('payments', 'stripe_public_key')) ) : ?>

             data-stripe-key="<?php echo esc_attr($stripe_key); ?>"
             <?php endif; ?>>

        <?php if ( VS_Admin_Settings::get_option('payments', 'stripe_public_key') ) : ?>
        <script src="https://js.stripe.com/v3/"></script>
        <?php endif; ?>

        <style>
        /* ── VS Modules UI ───────────────────────────────── */
        .vsm-wrap *{box-sizing:border-box;margin:0;padding:0}
        .vsm-wrap{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;color:#0f172a;padding:24px 0}
        .vsm-header{margin-bottom:20px}
        .vsm-header h2{font-size:20px;font-weight:700;color:#0f172a}
        .vsm-header p{font-size:13.5px;color:#64748b;margin-top:4px}

        /* toolbar */
        .vsm-toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:16px}
        .vsm-filters{display:flex;gap:6px;flex-wrap:wrap;flex:1}
        .vsm-filter-btn{border:1px solid #e2e8f0;background:#fff;color:#475569;font-size:12.5px;
            padding:6px 14px;border-radius:20px;cursor:pointer;transition:all .15s;font-weight:500}
        .vsm-filter-btn.active,.vsm-filter-btn:hover{background:#0f172a;color:#fff;border-color:#0f172a}
        .vsm-search{position:relative;min-width:200px}
        .vsm-search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:15px;height:15px;
            color:#94a3b8;pointer-events:none}
        .vsm-search input{width:100%;padding:7px 12px 7px 32px;border:1px solid #e2e8f0;
            border-radius:10px;font-size:13px;background:#fff;color:#0f172a;outline:none;transition:border .15s}
        .vsm-search input:focus{border-color:#94a3b8}
        .vsm-count{font-size:13px;color:#64748b;margin-bottom:12px}

        /* grid */
        .vsm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(255px,1fr));gap:14px}
        .vsm-card{background:#fff;border:1px solid #e8edf3;border-radius:14px;padding:18px;
            display:flex;flex-direction:column;gap:12px;transition:border-color .2s,box-shadow .2s;position:relative}
        .vsm-card:hover{border-color:#cbd5e1;box-shadow:0 4px 14px rgba(15,23,42,.07)}
        .vsm-card.vsm-locked{opacity:.75}

        /* card top */
        .vsm-card-top{display:flex;align-items:flex-start;gap:12px}
        .vsm-card-icon{width:40px;height:40px;border-radius:10px;display:flex;align-items:center;
            justify-content:center;flex-shrink:0}
        .vsm-card-icon svg{width:20px;height:20px}
        .vsm-card-meta{flex:1}
        .vsm-card-meta h3{font-size:14px;font-weight:700;color:#0f172a;line-height:1.3}

        /* badges */
        .vsm-badge{display:inline-block;font-size:11px;font-weight:600;padding:2px 9px;
            border-radius:20px;margin-top:3px;letter-spacing:.2px}
        .vsm-badge-free{background:#eaf3de;color:#3b6d11}
        .vsm-badge-pro{background:#eeedfe;color:#534ab7}

        /* desc */
        .vsm-card-desc{font-size:13px;color:#64748b;line-height:1.55;flex:1}

        /* footer */
        .vsm-card-footer{display:flex;align-items:center;justify-content:space-between;
            padding-top:10px;border-top:1px solid #f1f5f9;margin-top:auto}

        /* toggle */
        .vsm-toggle{position:relative;width:40px;height:22px;cursor:pointer;display:inline-block}
        .vsm-toggle input{opacity:0;width:0;height:0;position:absolute}
        .vsm-track{position:absolute;inset:0;border-radius:20px;background:#e2e8f0;
            transition:background .2s;border:1px solid #e2e8f0}
        .vsm-thumb{position:absolute;width:16px;height:16px;border-radius:50%;background:#fff;
            top:3px;left:3px;transition:transform .2s;box-shadow:0 1px 3px rgba(0,0,0,.18)}
        .vsm-toggle input:checked ~ .vsm-track{background:#2563eb;border-color:#2563eb}
        .vsm-toggle input:checked ~ .vsm-thumb{transform:translateX(18px)}
        .vsm-toggle-row{display:flex;align-items:center;gap:8px}
        .vsm-toggle-label{font-size:12px;color:#94a3b8;font-weight:500}
        .vsm-toggle input:checked ~ .vsm-toggle-label{display:none}/* handled by JS */

        /* settings btn */
        .vsm-settings-btn{font-size:12px;color:#475569;background:#f8fafc;border:1px solid #e2e8f0;
            border-radius:8px;padding:5px 12px;cursor:pointer;transition:all .15s;font-weight:500;
            text-decoration:none;display:inline-block}
        .vsm-settings-btn:hover{background:#f1f5f9;border-color:#cbd5e1;color:#0f172a}

        /* upgrade btn */
        .vsm-upgrade-btn{font-size:12px;color:#534ab7;background:#eeedfe;border:none;
            border-radius:8px;padding:6px 14px;cursor:pointer;font-weight:600;transition:background .15s}
        .vsm-upgrade-btn:hover{background:#d8d6f9}
        .vsm-lock{font-size:15px;color:#94a3b8}

        /* status text */
        .vsm-status-on{font-size:12px;color:#16a34a;font-weight:600}
        .vsm-status-off{font-size:12px;color:#94a3b8;font-weight:500}

        /* toast */
        #vsm-toast{position:fixed;bottom:28px;right:28px;background:#0f172a;color:#fff;
            padding:10px 18px;border-radius:10px;font-size:13px;font-weight:500;
            box-shadow:0 4px 16px rgba(0,0,0,.25);opacity:0;transition:opacity .25s;
            pointer-events:none;z-index:9999}
        #vsm-toast.show{opacity:1}

        /* empty */
        .vsm-empty{text-align:center;padding:48px 16px;color:#94a3b8;font-size:14px}

        /* Purchase modal styles - Premium Glassmorphism */
        .vsm-modal { position:fixed; inset:0; background:rgba(15,23,42,0.4); display:none; align-items:center; justify-content:center; z-index:10000; padding:20px; backdrop-filter:blur(8px); transition: all 0.3s ease; }
        .vsm-modal.show { display:flex; }
        .vsm-modal-content { background:rgba(255,255,255,0.95); border:1px solid rgba(255,255,255,0.3); border-radius:24px; width:100%; max-width:480px; box-shadow:0 25px 50px -12px rgba(0,0,0,0.25); overflow:hidden; animation:vsmPop 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
        @keyframes vsmPop { from { transform:scale(0.9); opacity:0 } to { transform:scale(1); opacity:1 } }
        
        .vsm-modal-header { padding:30px 30px 20px; text-align:center; position:relative; }
        .vsm-modal-header h3 { font-size:22px; font-weight:800; color:#0f172a; letter-spacing:-0.5px; }
        .vsm-modal-close { position:absolute; top:20px; right:20px; cursor:pointer; color:#94a3b8; border:none; background:#f1f5f9; width:32px; height:32px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:18px; transition:all 0.2s; }
        .vsm-modal-close:hover { background:#e2e8f0; color:#0f172a; transform:rotate(90deg); }
        
        .vsm-pay-summary { background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%); padding:24px; margin:0 30px 24px; border-radius:20px; color:#fff; display:flex; justify-content:space-between; align-items:center; box-shadow:0 10px 20px rgba(79, 70, 229, 0.2); }
        .vsm-pay-summary-label { font-size:13px; font-weight:600; text-transform:uppercase; letter-spacing:1px; opacity:0.8; }
        .vsm-pay-summary-val { font-size:28px; font-weight:800; color:#fff; }
        
        .vsm-modal-body { padding:0 30px 30px; }
        .vsm-pay-form { display:grid; gap:18px; }
        .vsm-input-group { display:flex; flex-direction:column; gap:6px; }
        .vsm-input-group label { font-size:13px; font-weight:700; color:#475569; display:flex; align-items:center; gap:6px; }
        .vsm-input-group label svg { width:14px; height:14px; opacity:0.7; }
        .vsm-input-group input { padding:12px 16px; border:2px solid #e2e8f0; border-radius:12px; font-size:14px; transition:all 0.2s; color:#0f172a; }
        .vsm-input-group input:focus { border-color:#4f46e5; outline:none; box-shadow:0 0 0 4px rgba(79, 70, 229, 0.1); }
        
        .vsm-stripe-container { border:2px solid #e2e8f0; padding:14px 16px; border-radius:12px; background:#fcfdfe; transition:all 0.2s; }
        .vsm-stripe-container.focused { border-color:#4f46e5; box-shadow:0 0 0 4px rgba(79, 70, 229, 0.1); }
        
        .vsm-pay-btn { background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); color:#fff; border:none; border-radius:14px; padding:16px; font-size:16px; font-weight:700; cursor:pointer; transition:all 0.2s; box-shadow: 0 4px 12px rgba(15, 23, 42, 0.15); margin-top:10px; }
        .vsm-pay-btn:hover { transform:translateY(-2px); box-shadow: 0 8px 20px rgba(15, 23, 42, 0.2); }
        .vsm-pay-btn:active { transform:translateY(0); }
        .vsm-pay-btn:disabled { opacity:.5; cursor:not-allowed; transform:none; }
        
        .vsm-secure-badges { display:flex; justify-content:center; gap:20px; margin-top:20px; opacity:0.6; }
        .vsm-badge-item { display:flex; align-items:center; gap:6px; font-size:11px; font-weight:600; color:#64748b; }
        .vsm-badge-item svg { width:16px; height:16px; }

        @media(max-width:640px){
            .vsm-grid{grid-template-columns:1fr}
            .vsm-toolbar{flex-direction:column;align-items:stretch}
        }
        </style>

        <div class="vsm-header">
            <h2><?php esc_html_e( 'Modules', 'vendor-space' ); ?></h2>
            <p><?php esc_html_e( 'Enable or disable features based on your needs. Changes take effect immediately.', 'vendor-space' ); ?></p>
        </div>

        <div class="vsm-toolbar">
            <div class="vsm-filters" id="vsm-filters">
                <?php
                $filter_labels = [
                    'all'      => __( 'All', 'vendor-space' ),
                    'active'   => __( 'Active', 'vendor-space' ),
                    'inactive' => __( 'Inactive', 'vendor-space' ),
                    'free'     => __( 'Free', 'vendor-space' ),
                    'pro'      => __( 'Pro', 'vendor-space' ),
                ];
                foreach ( $filter_labels as $key => $label ) {
                    $cls = $key === 'all' ? ' active' : '';
                    echo '<button class="vsm-filter-btn' . esc_attr( $cls ) . '" data-filter="' . esc_attr( $key ) . '">' . esc_html( $label ) . '</button>';
                }
                ?>
            </div>
            <div class="vsm-search">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                          d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
                </svg>
                <input type="text" id="vsm-search" placeholder="<?php esc_attr_e( 'Search modules...', 'vendor-space' ); ?>">
            </div>
        </div>

        <div class="vsm-count" id="vsm-count"></div>
        <div class="vsm-grid" id="vsm-grid">
            <?php
            foreach ( $registry as $id => $mod ) :
                $is_active = ! empty( $active[ $id ] );
                $is_pro    = $mod['type'] === 'pro';
                $c         = $colors[ $mod['color'] ] ?? $colors['gray'];
                $checked   = $is_active ? 'checked' : '';
                ?>
                <div class="vsm-card<?php echo $is_pro && ! $is_active ? ' vsm-locked' : ''; ?>"
                     data-module="<?php echo esc_attr( $id ); ?>"
                     data-type="<?php echo esc_attr( $mod['type'] ); ?>"
                     data-active="<?php echo $is_active ? '1' : '0'; ?>">

                    <div class="vsm-card-top">
                        <div class="vsm-card-icon"
                             style="background:<?php echo esc_attr( $c['bg'] ); ?>">
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
                                 stroke="<?php echo esc_attr( $c['icon'] ); ?>" stroke-width="2">
                                <path stroke-linecap="round" stroke-linejoin="round"
                                      d="<?php echo esc_attr( $mod['icon'] ); ?>"/>
                            </svg>
                        </div>
                        <div class="vsm-card-meta">
                            <h3><?php echo esc_html( $mod['name'] ); ?></h3>
                            <span class="vsm-badge vsm-badge-<?php echo esc_attr( $mod['type'] ); ?>">
                                <?php echo $is_pro ? esc_html__( 'Pro', 'vendor-space' ) : esc_html__( 'Free', 'vendor-space' ); ?>
                            </span>
                        </div>
                    </div>

                    <p class="vsm-card-desc"><?php echo esc_html( $mod['desc'] ); ?></p>

                    <div class="vsm-card-footer">
                        <?php
                        $is_purchased = self::is_purchased( $id );
                        $pro_class    = $mod['class'] ?? null;
                        $is_licensed  = $pro_class && class_exists( $pro_class );

                        // Logic handling for all cases
                        if ( $is_pro && ( ! $is_pro_active || ! $is_licensed ) ) : ?>
                            <div class="vsm-pro-action-wrap">
                                <?php if ( ! $is_pro_active ) : ?>
                                    <?php if ( $is_pro_installed ) : ?>
                                        <!-- Case: Pro plugin exists but not active -->
                                        <a href="<?php echo admin_url( 'plugins.php' ); ?>" class="vsm-activate-pro-btn">
                                            <i class="fa-solid fa-bolt"></i>
                                            <?php esc_html_e( 'Activate Pro Plugin', 'vendor-space' ); ?>
                                        </a>
                                    <?php elseif ( ! $is_purchased ) : ?>
                                        <!-- Case: Pro plugin not installed and not purchased -->
                                        <a class="vsm-buy-btn" href="https://vendor.edenstophotels.com/Checkout/?add-to-cart=15" target="_blank">
                                            <span class="vsm-lock">🔒</span>
                                            <?php echo sprintf( __( 'Get Pro ($%s)', 'vendor-space' ), $mod['price'] ?? '49.00' ); ?>
                                        </a>
                                    <?php else : ?>
                                        <!-- Case: Purchased but Pro plugin not installed -->
                                        <a class="vsm-buy-btn" href="#" style="opacity:0.7;cursor:default;">
                                            <?php esc_html_e( 'Purchased - Install Pro', 'vendor-space' ); ?>
                                        </a>
                                    <?php endif; ?>
                                <?php elseif ( ! $is_licensed ) : ?>
                                    <!-- Case: Pro plugin active but license is missing (Class not found) -->
                                    <a href="<?php echo admin_url( 'admin.php?page=vs-admin-license' ); ?>" class="vsm-activate-pro-btn" style="background: linear-gradient(135deg, #f59e0b, #d97706);padding:15px;">
                                        <i class="fa-solid fa-key"></i>
                                        <?php esc_html_e( 'Activate License', 'vendor-space' ); ?>
                                    </a>
                                <?php endif; ?>
                            </div>

                        <?php else : ?>
                            <!-- Case: Free module OR Pro module correctly licensed and active -->
                            <div class="vsm-toggle-row">
                                <label class="vsm-toggle" title="<?php echo $is_active ? esc_attr__( 'Deactivate', 'vendor-space' ) : esc_attr__( 'Activate', 'vendor-space' ); ?>">
                                    <input type="checkbox" class="vsm-toggle-input"
                                            data-module="<?php echo esc_attr( $id ); ?>"
                                            <?php echo $checked; ?>>
                                    <div class="vsm-track"></div>
                                    <div class="vsm-thumb"></div>
                                </label>
                                <span class="vsm-status-text <?php echo $is_active ? 'vsm-status-on' : 'vsm-status-off'; ?>">
                                    <?php echo $is_active ? esc_html__( 'Active', 'vendor-space' ) : esc_html__( 'Inactive', 'vendor-space' ); ?>
                                </span>
                            </div>

                           
                        <?php endif; ?>
                    </div>

                </div>
            <?php endforeach; ?>
        </div>

        <div class="vsm-empty" id="vsm-empty" style="display:none">
            <?php esc_html_e( 'No modules found.', 'vendor-space' ); ?>
        </div>

        <div id="vsm-toast"></div>

        <script>
        (function () {
            var app   = document.getElementById('vs-modules-app');
            var ajax  = app.dataset.ajax;
            var nonce = app.dataset.nonce;

            /* ── Filter & search ─────────────────────────── */
            var activeFilter = 'all';
            var searchQuery  = '';

            function applyFilters() {
                var cards = document.querySelectorAll('.vsm-card');
                var shown = 0;
                cards.forEach(function (card) {
                    var type   = card.dataset.type;
                    var isOn   = card.dataset.active === '1';
                    var name   = card.querySelector('h3').textContent.toLowerCase();
                    var match  = true;
                    if (activeFilter === 'active'   && !isOn)        match = false;
                    if (activeFilter === 'inactive' && isOn)         match = false;
                    if (activeFilter === 'free'     && type !== 'free') match = false;
                    if (activeFilter === 'pro'      && type !== 'pro')  match = false;
                    if (searchQuery && name.indexOf(searchQuery) === -1) match = false;
                    card.style.display = match ? '' : 'none';
                    if (match) shown++;
                });
                document.getElementById('vsm-count').textContent =
                    shown + ' ' + (shown !== 1 ? '<?php echo esc_js( __( 'modules', 'vendor-space' ) ); ?>' : '<?php echo esc_js( __( 'module', 'vendor-space' ) ); ?>');
                document.getElementById('vsm-empty').style.display = shown ? 'none' : '';
            }

            document.getElementById('vsm-filters').addEventListener('click', function (e) {
                var btn = e.target.closest('.vsm-filter-btn');
                if (!btn) return;
                document.querySelectorAll('.vsm-filter-btn').forEach(function (b) { b.classList.remove('active'); });
                btn.classList.add('active');
                activeFilter = btn.dataset.filter;
                applyFilters();
            });

            document.getElementById('vsm-search').addEventListener('input', function () {
                searchQuery = this.value.toLowerCase().trim();
                applyFilters();
            });

            applyFilters(); // run once on load

            /* ── Toggle handler ──────────────────────────── */
            document.querySelectorAll('.vsm-toggle-input').forEach(function (toggle) {
                toggle.addEventListener('change', function () {
                    var moduleId = this.dataset.module;
                    var enabled  = this.checked;
                    var card     = this.closest('.vsm-card');
                    var label    = card.querySelector('.vsm-status-text');
                    this.disabled = true;

                    var body = new URLSearchParams();
                    body.append('action',  'vs_toggle_module');
                    body.append('nonce',   nonce);
                    body.append('module',  moduleId);
                    body.append('enabled', enabled ? '1' : '0');

                    fetch(ajax, { method: 'POST', body: body })
                        .then(function (r) { return r.json(); })
                        .then(function (data) {
                            if (data.success) {
                                card.dataset.active = enabled ? '1' : '0';
                                if (label) {
                                    label.textContent = enabled
                                        ? '<?php echo esc_js( __( 'Active', 'vendor-space' ) ); ?>'
                                        : '<?php echo esc_js( __( 'Inactive', 'vendor-space' ) ); ?>';
                                    label.className = 'vsm-status-text ' + (enabled ? 'vsm-status-on' : 'vsm-status-off');
                                }
                                showToast(data.data.message, 'success');
                                applyFilters();
                                location.reload();
                            } else {
                                /* revert toggle */
                                toggle.checked = !enabled;
                                showToast(data.data.message, 'error');
                            }
                        })
                        .catch(function () {
                            toggle.checked = !enabled;
                            showToast('<?php echo esc_js( __( 'Connection failed.', 'vendor-space' ) ); ?>', 'error');
                        })
                        .finally(function () { toggle.disabled = false; });
                });
            });

            /* ── Toast ───────────────────────────────────── */
            var toastTimer;
            function showToast(msg, type) {
                var el = document.getElementById('vsm-toast');
                if (!el) return;
                el.textContent = msg;
                el.style.background = type === 'error' ? '#b91c1c' : '#16a34a';
                el.classList.add('show');
                clearTimeout(toastTimer);
                toastTimer = setTimeout(function () { el.classList.remove('show'); }, 2800);
            }
        })();
        </script>

        </div><!-- .vsm-wrap -->
        <?php
    }

}
