<?php
/**
 * DBA_SEO_Sniper_Admin — Settings page, keyword manager, analysis dashboard
 *
 * UI flow:
 *   1. Type keyword → auto-resolve suggests best bot + theme
 *   2. User can OVERRIDE bot, theme, and language from dropdowns
 *   3. Analyze = crawl Google + show competitor data
 *   4. Generate = crawl + analyze + route to chosen bot with competitive brief
 *
 * @since 2.16.0
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class DBA_SEO_Sniper_Admin {

    private static $instance = null;

    public static function get_instance() {
        if ( null === self::$instance ) self::$instance = new self();
        return self::$instance;
    }

    private function __construct() {
        add_action( 'admin_menu', array( $this, 'menu' ), 46 );
        add_action( 'wp_ajax_dba_sniper_analyze',         array( $this, 'ajax_analyze' ) );
        add_action( 'wp_ajax_dba_sniper_generate',         array( $this, 'ajax_generate' ) );
        add_action( 'wp_ajax_dba_sniper_add_keyword',      array( $this, 'ajax_add_keyword' ) );
        add_action( 'wp_ajax_dba_sniper_del_keyword',      array( $this, 'ajax_del_keyword' ) );
        add_action( 'wp_ajax_dba_sniper_resolve',          array( $this, 'ajax_resolve' ) );
        add_action( 'wp_ajax_dba_sniper_get_bots',         array( $this, 'ajax_get_bots' ) );
        add_action( 'wp_ajax_dba_sniper_save_api_key',     array( $this, 'ajax_save_api_key' ) );
        add_action( 'wp_ajax_dba_sniper_progress',         array( $this, 'ajax_progress' ) );
        add_action( 'wp_ajax_dba_sniper_repair',           array( $this, 'ajax_repair' ) );
        add_action( 'wp_ajax_dba_sniper_import_tis',        array( $this, 'ajax_import_tis' ) );
    }

    public function menu() {
        add_submenu_page(
            'dba-settings',
            'SEO Sniper — Competitive Content',
            '🎯 SEO Sniper',
            'manage_options',
            'dba-seo-sniper',
            array( $this, 'page' )
        );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Return all bots + themes as JSON (for JS dropdowns)
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_get_bots() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );
        wp_send_json_success( DBA_SEO_Sniper_Router::get_all_bots() );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Save Serper API key
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_save_api_key() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );

        $key = sanitize_text_field( wp_unslash( $_POST['api_key'] ?? '' ) );
        if ( empty( $key ) ) wp_send_json_error( 'No API key provided.' );

        DBA_SEO_Sniper_Crawler::set_api_key( $key );
        wp_send_json_success( array( 'message' => 'Serper API key saved.' ) );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Resolve keyword → best bot + theme (auto-suggest)
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_resolve() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );

        $keyword  = sanitize_text_field( wp_unslash( $_POST['keyword'] ?? '' ) );
        $language = sanitize_key( $_POST['language'] ?? 'en' );
        if ( empty( $keyword ) ) wp_send_json_error( 'No keyword.' );

        $route = DBA_SEO_Sniper_Router::resolve( $keyword, $language );
        if ( is_wp_error( $route ) ) {
            wp_send_json_error( $route->get_error_message() );
        }

        wp_send_json_success( $route );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Analyze keyword (crawl + competitor analysis only)
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_analyze() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );

        $keyword  = sanitize_text_field( wp_unslash( $_POST['keyword'] ?? '' ) );
        $language = sanitize_key( $_POST['language'] ?? 'en' );
        if ( empty( $keyword ) ) wp_send_json_error( 'No keyword provided.' );

        @set_time_limit( 120 );

        $serp_data = DBA_SEO_Sniper_Crawler::crawl_serp( $keyword, $language );
        if ( is_wp_error( $serp_data ) ) wp_send_json_error( $serp_data->get_error_message() );
        $serp = $serp_data['organic'] ?? $serp_data; // backward compat

        $analysis = DBA_SEO_Sniper_Analyzer::analyze( $keyword, $serp, $language );

        $keywords = get_option( 'dba_sniper_keywords', array() );
        $kw_key = sanitize_key( $keyword . '_' . $language );
        $keywords[ $kw_key ]['keyword']       = $keyword;
        $keywords[ $kw_key ]['language']       = $language;
        $keywords[ $kw_key ]['last_analysis']  = $analysis;
        $keywords[ $kw_key ]['last_analyzed']  = current_time( 'mysql' );
        update_option( 'dba_sniper_keywords', $keywords, false );

        wp_send_json_success( $analysis );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Generate — route to chosen bot with competitive intel
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_generate() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );

        $keyword    = sanitize_text_field( wp_unslash( $_POST['keyword'] ?? '' ) );
        $language   = sanitize_key( $_POST['language'] ?? 'en' );
        $bot_id     = sanitize_key( $_POST['bot_id'] ?? '' );
        $theme_slug = sanitize_key( $_POST['theme_slug'] ?? '' );

        if ( empty( $keyword ) )    wp_send_json_error( 'No keyword provided.' );
        if ( empty( $bot_id ) )     wp_send_json_error( 'No bot selected.' );
        if ( empty( $theme_slug ) ) wp_send_json_error( 'No theme selected.' );

        @set_time_limit( 300 );

        $result = DBA_SEO_Sniper_Router::execute( $keyword, $language, $bot_id, $theme_slug );

        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        }

        $keywords = get_option( 'dba_sniper_keywords', array() );
        $kw_key   = sanitize_key( $keyword . '_' . $language );
        $keywords[ $kw_key ]['keyword']        = $keyword;
        $keywords[ $kw_key ]['language']        = $language;
        $keywords[ $kw_key ]['last_post_id']   = $result['post_id'];
        $keywords[ $kw_key ]['last_generated'] = current_time( 'mysql' );
        $keywords[ $kw_key ]['last_bot']       = $result['bot'];
        $keywords[ $kw_key ]['last_theme']     = $result['theme'];
        if ( ! empty( $result['analysis'] ) ) {
            $keywords[ $kw_key ]['last_analysis'] = $result['analysis'];
            $keywords[ $kw_key ]['last_analyzed']  = current_time( 'mysql' );
        }
        update_option( 'dba_sniper_keywords', $keywords, false );

        wp_send_json_success( array(
            'post_id'      => $result['post_id'],
            'bot'          => $result['bot'],
            'theme'        => $result['theme'],
            'language'     => $result['language'],
            'edit_url'     => get_edit_post_link( $result['post_id'], 'raw' ),
            'message'      => 'Post #' . $result['post_id'] . ' created via ' . $result['bot'] . ' → "' . $result['theme'] . '" (' . $result['language'] . ')',
            'verification' => $result['verification'] ?? array(),
        ) );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Poll generation progress (called every 2s by JS)
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_progress() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        wp_send_json_success( DBA_SEO_Sniper_Router::get_progress() );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Repair post (re-run DALL-E, Yoast, etc.)
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_repair() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );

        $post_id = intval( $_POST['post_id'] ?? 0 );
        if ( ! $post_id ) wp_send_json_error( 'No post ID.' );

        $repairs = DBA_SEO_Sniper_Router::repair_post( $post_id );
        if ( is_wp_error( $repairs ) ) wp_send_json_error( $repairs->get_error_message() );

        wp_send_json_success( $repairs );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Add / Remove keywords
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_add_keyword() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );
        $keyword    = sanitize_text_field( wp_unslash( $_POST['keyword'] ?? '' ) );
        $language   = sanitize_key( $_POST['language'] ?? 'en' );
        $bot_id     = sanitize_key( $_POST['bot_id'] ?? '' );
        $theme_slug = sanitize_key( $_POST['theme_slug'] ?? '' );
        if ( empty( $keyword ) ) wp_send_json_error( 'No keyword.' );

        // Auto-resolve if bot/theme not provided
        if ( empty( $bot_id ) || empty( $theme_slug ) ) {
            $route = DBA_SEO_Sniper_Router::resolve( $keyword, $language );
            if ( ! is_wp_error( $route ) ) {
                $bot_id     = $route['bot_id'];
                $theme_slug = $route['theme_slug'];
            }
        }

        $keywords = get_option( 'dba_sniper_keywords', array() );
        $kw_key = sanitize_key( $keyword . '_' . $language );
        $keywords[ $kw_key ] = array_merge( $keywords[ $kw_key ] ?? array(), array(
            'keyword'    => $keyword,
            'language'   => $language,
            'added'      => $keywords[ $kw_key ]['added'] ?? current_time( 'mysql' ),
            'status'     => 'tracked',
            'last_bot'   => $bot_id,
            'last_theme' => $theme_slug,
        ) );
        update_option( 'dba_sniper_keywords', $keywords, false );

        wp_send_json_success( array(
            'count'      => count( $keywords ),
            'bot_id'     => $bot_id,
            'theme_slug' => $theme_slug,
        ) );
    }

    public function ajax_del_keyword() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );
        $kw_key = sanitize_key( $_POST['kw_key'] ?? '' );
        if ( empty( $kw_key ) ) wp_send_json_error( 'No key.' );
        $keywords = get_option( 'dba_sniper_keywords', array() );
        unset( $keywords[ $kw_key ] );
        update_option( 'dba_sniper_keywords', $keywords, false );
        wp_send_json_success();
    }

    /* ═══════════════════════════════════════════════════════════════
     *  AJAX: Import TIS keyword suggestions into tracked keywords
     * ═══════════════════════════════════════════════════════════════ */

    public function ajax_import_tis() {
        check_ajax_referer( 'dba_admin_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( 'Forbidden' );

        // Accept specific keywords or "all"
        $import_mode = sanitize_text_field( $_POST['mode'] ?? 'all' );
        $specific    = isset( $_POST['keywords'] ) ? array_map( 'sanitize_text_field', (array) $_POST['keywords'] ) : array();

        if ( ! class_exists( 'DBA_TIS_Recommender' ) ) {
            wp_send_json_error( 'TIS module not loaded.' );
        }

        // Get TIS keyword queue
        $tis_queue = DBA_TIS_Recommender::get_sniper_queue();
        if ( empty( $tis_queue ) ) {
            wp_send_json_error( 'TIS queue is empty. Run a TIS scan first.' );
        }

        $keywords = get_option( 'dba_sniper_keywords', array() );
        $imported = 0;
        $skipped  = 0;

        foreach ( $tis_queue as $item ) {
            $kw_text = $item['keyword'] ?? '';
            if ( empty( $kw_text ) ) continue;

            // If specific mode, only import selected keywords
            if ( $import_mode === 'selected' && ! in_array( $kw_text, $specific, true ) ) continue;

            $language = 'en'; // TIS currently scans EN; extend later
            $kw_key   = sanitize_key( $kw_text . '_' . $language );

            // Skip if already tracked
            if ( isset( $keywords[ $kw_key ] ) ) {
                $skipped++;
                continue;
            }

            // Auto-resolve bot + theme
            $bot_id     = '';
            $theme_slug = '';
            if ( class_exists( 'DBA_SEO_Sniper_Router' ) ) {
                $route = DBA_SEO_Sniper_Router::resolve( $kw_text, $language );
                if ( ! is_wp_error( $route ) ) {
                    $bot_id     = $route['bot_id'];
                    $theme_slug = $route['theme_slug'];
                }
            }

            $keywords[ $kw_key ] = array(
                'keyword'    => $kw_text,
                'language'   => $language,
                'added'      => current_time( 'mysql' ),
                'status'     => 'tracked',
                'last_bot'   => $bot_id,
                'last_theme' => $theme_slug,
                'source'     => 'TIS: ' . ( $item['source'] ?? 'auto' ),
                'tis_priority' => $item['priority'] ?? 'medium',
                'tis_grade'    => $item['grade'] ?? null,
            );
            $imported++;
        }

        update_option( 'dba_sniper_keywords', $keywords, false );

        error_log( 'SEO Sniper: Imported ' . $imported . ' TIS keywords, skipped ' . $skipped . ' (already tracked).' );

        wp_send_json_success( array(
            'imported' => $imported,
            'skipped'  => $skipped,
            'total'    => count( $keywords ),
        ) );
    }

    /* ═══════════════════════════════════════════════════════════════
     *  ADMIN PAGE
     * ═══════════════════════════════════════════════════════════════ */

    public function page() {
        $kw = get_option( 'dba_sniper_keywords', array() );

        global $wpdb;
        $total_posts = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID WHERE pm.meta_key = '_dba_sniper_generated' AND p.post_status IN ('publish','draft','pending')" );

        // Build bot list for status card
        $bots = DBA_SEO_Sniper_Router::get_all_bots();
        $active_bots  = 0;
        $wired_bots   = 0;
        foreach ( $bots as $b ) {
            if ( $b['status'] === 'active' ) $active_bots++;
            if ( ! empty( $b['wired'] ) && $b['status'] === 'active' ) $wired_bots++;
        }

        $serper_key   = DBA_SEO_Sniper_Crawler::get_api_key();
        $has_key      = ! empty( $serper_key );
        $serper_usage = DBA_SEO_Sniper_Crawler::get_usage();
        $month_key    = date( 'Y-m' );
        $used_total   = $serper_usage['total'] ?? 0;
        $used_month   = $serper_usage['monthly'][ $month_key ] ?? 0;
        $remaining    = max( 0, 2500 - $used_total ); // Free tier estimate
        ?>
        <div class="wrap" style="max-width:1100px">
        <h1 style="display:flex;align-items:center;gap:10px">
            <span style="font-size:32px">🎯</span> SEO Sniper — Competitive Content Engine
            <span style="background:#dc2626;color:#fff;padding:3px 12px;border-radius:4px;font-size:13px">v2.19.0</span>
        </h1>
        <p style="font-size:15px;color:#555">Scrape Google's top 20 → analyze competitors → feed intelligence into ANY bot → generate posts that outrank them.</p>

        <!-- STATUS -->
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin:20px 0">
            <div style="background:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:14px;text-align:center">
                <div style="font-size:24px;font-weight:bold;color:<?php echo $has_key ? '#166534' : '#dc2626'; ?>"><?php echo $has_key ? '✓' : '✕'; ?></div>
                <div style="font-size:11px;color:#666">Serper API</div>
            </div>
            <div style="background:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:14px;text-align:center">
                <div style="font-size:24px;font-weight:bold;color:#2563eb"><?php echo $used_total; ?>/2500</div>
                <div style="font-size:11px;color:#666">API Calls Used</div>
            </div>
            <div style="background:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:14px;text-align:center">
                <div style="font-size:24px;font-weight:bold;color:#059669"><?php echo $used_month; ?></div>
                <div style="font-size:11px;color:#666">This Month</div>
            </div>
            <div style="background:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:14px;text-align:center">
                <div style="font-size:24px;font-weight:bold;color:#7c3aed"><?php echo count( $kw ); ?></div>
                <div style="font-size:11px;color:#666">Keywords Tracked</div>
            </div>
            <div style="background:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:14px;text-align:center">
                <div style="font-size:24px;font-weight:bold;color:#dc2626"><?php echo intval( $total_posts ); ?></div>
                <div style="font-size:11px;color:#666">Posts Created</div>
            </div>
            <div style="background:#fff;border:1px solid #e0e0e0;border-radius:8px;padding:14px;text-align:center">
                <?php $tis_connected = class_exists( 'DBA_TIS_Recommender' ); ?>
                <div style="font-size:24px;font-weight:bold;color:<?php echo $tis_connected ? '#f59e0b' : '#999'; ?>"><?php echo $tis_connected ? '🔬' : '—'; ?></div>
                <div style="font-size:11px;color:#666">TIS <?php echo $tis_connected ? 'Connected' : 'Not loaded'; ?></div>
            </div>
        </div>

        <!-- SERPER API KEY -->
        <?php if ( ! $has_key ) : ?>
        <div style="background:#fef2f2;border:2px solid #dc2626;border-radius:10px;padding:16px;margin:10px 0">
            <h3 style="margin:0 0 8px;color:#991b1b">⚠️ Serper API Key Required</h3>
            <p style="margin:0 0 10px;font-size:13px;color:#991b1b">Paste your <a href="https://serper.dev" target="_blank">serper.dev</a> API key to enable Google rank tracking and competitor analysis.</p>
            <div style="display:flex;gap:8px">
                <input type="text" id="sniper-api-key" placeholder="Paste Serper API key here" style="flex:1;padding:8px 12px;font-size:14px;border:1px solid #ccc;border-radius:6px">
                <button type="button" id="sniper-save-key" class="button button-primary" style="padding:8px 16px">Save Key</button>
            </div>
        </div>
        <?php else : ?>
        <details style="margin:10px 0">
            <summary style="cursor:pointer;font-size:13px;color:#888">🔑 Serper API Key: <?php echo esc_html( substr( $serper_key, 0, 8 ) . '••••••••' ); ?> — <strong style="color:#059669">~<?php echo $remaining; ?> calls remaining</strong></summary>
            <div style="display:flex;gap:8px;margin-top:8px">
                <input type="text" id="sniper-api-key" value="<?php echo esc_attr( $serper_key ); ?>" style="flex:1;max-width:400px;padding:6px 10px;font-size:13px;border:1px solid #ccc;border-radius:4px">
                <button type="button" id="sniper-save-key" class="button" style="padding:6px 12px;font-size:12px">Update Key</button>
            </div>
        </details>
        <?php endif; ?>

        <!-- BOT OVERVIEW -->
        <details style="margin:10px 0">
            <summary style="cursor:pointer;font-weight:600;font-size:14px;color:#1e40af">📡 All Bots (<?php echo $active_bots; ?> active, <?php echo $wired_bots; ?> wired)</summary>
            <table class="widefat" style="margin-top:8px;font-size:13px;max-width:800px">
                <thead><tr><th>Bot</th><th>Status</th><th>Wired</th><th>Themes</th><th>Languages</th></tr></thead>
                <tbody>
                <?php foreach ( $bots as $id => $b ) : ?>
                <tr>
                    <td><strong><?php echo esc_html( $b['short'] ?? $id ); ?></strong><br><span style="font-size:11px;color:#888"><?php echo esc_html( $id ); ?></span></td>
                    <td><?php echo $b['status'] === 'active' ? '<span style="color:#166534">● Active</span>' : '<span style="color:#999">○ Not loaded</span>'; ?></td>
                    <td><?php echo ! empty( $b['wired'] ) ? '✅ Ready' : '<span style="color:#999">⏳ Planned</span>'; ?></td>
                    <td><?php echo count( $b['themes'] ?? array() ); ?></td>
                    <td><?php echo esc_html( implode( ', ', array_map( 'strtoupper', $b['languages'] ?? array() ) ) ); ?></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        </details>

        <!-- ═══ TIS INTELLIGENCE FEED ═══ -->
        <?php
        $tis_queue = array();
        $tis_date  = '';
        if ( class_exists( 'DBA_TIS_Recommender' ) ) {
            $tis_data  = get_option( 'dba_tis_sniper_queue', array() );
            $tis_queue = $tis_data['keywords'] ?? array();
            $tis_date  = $tis_data['generated_at'] ?? '';
        }
        if ( ! empty( $tis_queue ) ) :
            $priority_colors = array( 'critical' => '#dc2626', 'high' => '#ea580c', 'medium' => '#ca8a04', 'low' => '#65a30d' );
            $already_tracked = array_map( function( $d ) { return strtolower( $d['keyword'] ?? '' ); }, $kw );
        ?>
        <div style="background:#fff;border:2px solid #f59e0b;border-radius:10px;padding:20px;margin:20px 0">
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
                <h2 style="margin:0;color:#92400e">🔬 TIS Intelligence Feed — <?php echo count( $tis_queue ); ?> Keywords</h2>
                <div style="display:flex;gap:8px;align-items:center">
                    <span style="font-size:11px;color:#888">Last scan: <?php echo esc_html( $tis_date ); ?></span>
                    <button type="button" id="sniper-import-all-tis" class="button" style="background:#f59e0b;border-color:#f59e0b;color:#fff;font-size:13px;padding:6px 16px">
                        ⚡ Import All to Tracker
                    </button>
                </div>
            </div>
            <p style="font-size:12px;color:#78716c;margin:0 0 12px">Keywords pushed automatically by TIS based on content gaps, blind spots, and SEO title deficiencies. Import them to start tracking ranks and generating counter-content.</p>
            <table class="widefat striped" style="font-size:13px">
                <thead>
                    <tr>
                        <th>Keyword</th>
                        <th>Source</th>
                        <th>Type</th>
                        <th>Priority</th>
                        <th>Grade</th>
                        <th>Status</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                <?php foreach ( $tis_queue as $tq ) :
                    $is_tracked = in_array( strtolower( $tq['keyword'] ), $already_tracked, true );
                    $pcolor     = $priority_colors[ $tq['priority'] ] ?? '#888';
                    $type_label = str_replace( '_', ' ', ucfirst( $tq['type'] ?? 'gap' ) );
                ?>
                <tr>
                    <td><strong><?php echo esc_html( $tq['keyword'] ); ?></strong></td>
                    <td style="font-size:11px;color:#666"><?php echo esc_html( $tq['source'] ?? '—' ); ?></td>
                    <td><span style="background:#f0f0f0;padding:2px 8px;border-radius:3px;font-size:11px"><?php echo esc_html( $type_label ); ?></span></td>
                    <td><span style="color:<?php echo $pcolor; ?>;font-weight:bold;font-size:12px"><?php echo esc_html( strtoupper( $tq['priority'] ?? '' ) ); ?></span></td>
                    <td><?php if ( $tq['grade'] ) : ?><span style="background:#fef2f2;color:#dc2626;padding:2px 8px;border-radius:3px;font-weight:bold"><?php echo esc_html( $tq['grade'] ); ?></span><?php else : ?>—<?php endif; ?></td>
                    <td><?php echo $is_tracked
                        ? '<span style="color:#059669;font-weight:600">✓ Tracked</span>'
                        : '<span style="color:#dc2626">Not tracked</span>'; ?></td>
                    <td><?php if ( ! $is_tracked ) : ?>
                        <button class="button button-small sniper-import-tis-one" data-kw="<?php echo esc_attr( $tq['keyword'] ); ?>" style="background:#f59e0b;border-color:#f59e0b;color:#fff;font-size:11px">+ Track</button>
                    <?php else : ?>
                        <span style="color:#888;font-size:11px">—</span>
                    <?php endif; ?></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        </div>
        <?php endif; ?>

        <!-- ═══ ANALYZE & GENERATE ═══ -->
        <div style="background:#fff;border:2px solid #2563eb;border-radius:10px;padding:24px;margin:20px 0">
            <h2 style="margin:0 0 16px;color:#1e40af">🔍 Analyze & Generate</h2>

            <!-- Row 1: Keyword + Language -->
            <div style="display:flex;gap:10px;flex-wrap:wrap;align-items:end">
                <div>
                    <label style="font-size:13px;font-weight:600;color:#333">Target Keyword</label><br>
                    <input type="text" id="sniper-kw" placeholder="e.g. soparfi luxembourg" style="width:350px;padding:8px 12px;font-size:15px;border:1px solid #ccc;border-radius:6px">
                </div>
                <div>
                    <label style="font-size:13px;font-weight:600;color:#333">Target Language</label><br>
                    <select id="sniper-lang" style="padding:8px 12px;font-size:15px;border:1px solid #ccc;border-radius:6px">
                        <option value="en">🇬🇧 English</option>
                        <option value="fr">🇫🇷 French</option>
                        <option value="it">🇮🇹 Italian</option>
                        <option value="de">🇩🇪 German</option>
                        <option value="es">🇪🇸 Spanish</option>
                        <option value="pt">🇵🇹 Portuguese</option>
                        <option value="nl">🇳🇱 Dutch</option>
                    </select>
                </div>
            </div>

            <!-- Row 2: Bot + Theme (auto-filled, overridable) -->
            <div style="display:flex;gap:10px;flex-wrap:wrap;align-items:end;margin-top:12px">
                <div>
                    <label style="font-size:13px;font-weight:600;color:#333">Route to Bot</label><br>
                    <select id="sniper-bot" style="padding:8px 12px;font-size:14px;border:1px solid #ccc;border-radius:6px;min-width:280px">
                        <option value="">— type keyword to auto-detect —</option>
                    </select>
                </div>
                <div>
                    <label style="font-size:13px;font-weight:600;color:#333">Theme / Subject</label><br>
                    <select id="sniper-theme" style="padding:8px 12px;font-size:14px;border:1px solid #ccc;border-radius:6px;min-width:250px">
                        <option value="">— select bot first —</option>
                    </select>
                </div>
            </div>

            <!-- Auto-resolve feedback -->
            <div id="sniper-route-info" style="margin-top:10px"></div>

            <!-- Row 3: Action buttons -->
            <div style="display:flex;gap:10px;margin-top:16px;flex-wrap:wrap">
                <button type="button" id="sniper-analyze" class="button button-primary" style="background:#2563eb;border-color:#2563eb;font-size:14px;padding:8px 20px">
                    🔍 Analyze Competitors
                </button>
                <button type="button" id="sniper-generate" class="button" style="background:#7c3aed;border-color:#7c3aed;color:#fff;font-size:14px;padding:8px 20px;display:none">
                    🚀 Generate Post
                </button>
                <button type="button" id="sniper-save-kw" class="button" style="font-size:14px;padding:8px 20px">
                    💾 Save Keyword
                </button>
            </div>

            <!-- Progress -->
            <div id="sniper-progress" style="display:none;margin-top:16px">
                <div style="background:#e2e8f0;border-radius:8px;height:28px;overflow:hidden">
                    <div id="sniper-bar" style="height:100%;width:0%;background:linear-gradient(90deg,#2563eb,#7c3aed);border-radius:8px;transition:width .5s;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px;font-weight:bold">0%</div>
                </div>
                <div id="sniper-status" style="font-size:14px;color:#1e40af;font-weight:600;margin-top:8px"></div>
            </div>

            <!-- Analysis results -->
            <div id="sniper-results" style="display:none;margin-top:20px"></div>
        </div>

        <!-- RANK TRACKING -->
        <div style="background:#fff;border:2px solid #059669;border-radius:10px;padding:20px;margin:20px 0">
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
                <h2 style="margin:0;color:#065f46">📊 Rank Tracker</h2>
                <div style="display:flex;gap:10px;align-items:center">
                    <span style="font-size:12px;color:#888">
                        Next auto-check: <strong><?php echo esc_html( DBA_SEO_Sniper_Rank_Tracker::get_next_check() ?? 'Not scheduled' ); ?></strong>
                        <?php $last = get_option( 'dba_sniper_last_rank_check', '' ); if ( $last ) echo ' | Last: <strong>' . esc_html( $last ) . '</strong>'; ?>
                    </span>
                    <button type="button" id="sniper-check-all-ranks" class="button" style="background:#059669;border-color:#059669;color:#fff;font-size:13px;padding:6px 16px">
                        🔄 Check All Ranks Now
                    </button>
                </div>
            </div>

            <?php if ( ! empty( $kw ) ) : ?>
            <table class="widefat striped" style="font-size:13px">
                <thead>
                    <tr>
                        <th>Keyword</th>
                        <th>Lang</th>
                        <th>Bot → Theme</th>
                        <th style="text-align:center">Rank & Trend</th>
                        <th>Best</th>
                        <th>Last Checked</th>
                        <th>Post</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                <?php foreach ( $kw as $key => $data ) :
                    $a = $data['last_analysis'] ?? null;
                    $kw_text = $data['keyword'] ?? $key;
                    $kw_lang = $data['language'] ?? 'en';
                ?>
                <tr id="row-<?php echo esc_attr( $key ); ?>">
                    <td><strong><?php echo esc_html( $kw_text ); ?></strong></td>
                    <td><?php echo esc_html( strtoupper( $kw_lang ) ); ?></td>
                    <td style="font-size:12px"><?php echo ! empty( $data['last_bot'] ) ? esc_html( $data['last_bot'] . ' → ' . ( $data['last_theme'] ?? '?' ) ) : '<em style="color:#888">—</em>'; ?></td>
                    <td style="text-align:center" class="rank-cell" data-key="<?php echo esc_attr( $key ); ?>">
                        <?php echo DBA_SEO_Sniper_Rank_Tracker::render_rank_badge( $key ); ?>
                    </td>
                    <td>
                        <?php
                        $trend = DBA_SEO_Sniper_Rank_Tracker::compute_trend( $key );
                        echo $trend['best'] > 0 ? '<span style="color:#166534;font-weight:600">#' . $trend['best'] . '</span>' : '—';
                        ?>
                    </td>
                    <td style="font-size:11px"><?php echo esc_html( $data['last_rank_check'] ?? '—' ); ?></td>
                    <td><?php if ( ! empty( $data['last_post_id'] ) ) : ?>
                        <a href="<?php echo get_edit_post_link( $data['last_post_id'], 'raw' ); ?>" target="_blank">#<?php echo $data['last_post_id']; ?></a>
                        <button class="button button-small sniper-repair" data-post-id="<?php echo esc_attr( $data['last_post_id'] ); ?>" title="Repair: re-run DALL-E, Yoast, checks" style="margin-left:4px">🔧</button>
                    <?php else : ?>—<?php endif; ?></td>
                    <td style="white-space:nowrap">
                        <button class="button button-small sniper-check-rank" data-kw="<?php echo esc_attr( $kw_text ); ?>" data-lang="<?php echo esc_attr( $kw_lang ); ?>" data-key="<?php echo esc_attr( $key ); ?>" title="Check rank now">📍</button>
                        <button class="button button-small sniper-re-analyze" data-kw="<?php echo esc_attr( $kw_text ); ?>" data-lang="<?php echo esc_attr( $kw_lang ); ?>" data-bot="<?php echo esc_attr( $data['last_bot'] ?? '' ); ?>" data-theme="<?php echo esc_attr( $data['last_theme'] ?? '' ); ?>" title="Analyze competitors">🔍</button>
                        <button class="button button-small sniper-re-generate" data-kw="<?php echo esc_attr( $kw_text ); ?>" data-lang="<?php echo esc_attr( $kw_lang ); ?>" data-bot="<?php echo esc_attr( $data['last_bot'] ?? '' ); ?>" data-theme="<?php echo esc_attr( $data['last_theme'] ?? '' ); ?>" title="Generate post">🚀</button>
                        <button class="button button-small sniper-del" data-key="<?php echo esc_attr( $key ); ?>" style="color:#c53030" title="Delete">✕</button>
                    </td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
            <?php else : ?>
            <p style="color:#888;text-align:center;padding:20px">No keywords tracked yet. Add a keyword above and save it.</p>
            <?php endif; ?>
        </div>

        </div>

        <!-- GENERATION PROGRESS MODAL -->
        <div id="sniper-gen-modal" style="display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.6);z-index:99999;align-items:center;justify-content:center">
            <div style="background:#fff;border-radius:12px;padding:28px;max-width:540px;width:90%;box-shadow:0 20px 60px rgba(0,0,0,.3)">
                <h3 id="gen-modal-title" style="margin:0 0 16px;font-size:18px;color:#1e40af">🚀 Generating SEO-Optimized Post</h3>
                <div id="gen-modal-steps" style="margin:12px 0"></div>
                <div style="background:#e2e8f0;border-radius:8px;height:24px;overflow:hidden;margin:16px 0">
                    <div id="gen-modal-bar" style="height:100%;width:0%;background:linear-gradient(90deg,#2563eb,#7c3aed);border-radius:8px;transition:width .6s ease"></div>
                </div>
                <div id="gen-modal-status" style="font-size:13px;color:#64748b;text-align:center"></div>
                <div id="gen-modal-result" style="display:none;margin-top:16px;text-align:center"></div>
            </div>
        </div>

        <script>
        jQuery(function($){
            var A='<?php echo admin_url("admin-ajax.php"); ?>',
                N='<?php echo wp_create_nonce("dba_admin_nonce"); ?>',
                resolveTimer=null,
                BOTS={};

            // ── Save Serper API key ──
            $(document).on('click', '#sniper-save-key', function(){
                var key = $('#sniper-api-key').val().trim();
                if (!key) { alert('Paste your Serper API key.'); return; }
                var btn = $(this).prop('disabled',1).text('Saving...');
                $.post(A, {action:'dba_sniper_save_api_key', nonce:N, api_key:key}, function(r){
                    btn.prop('disabled',0).text('Save Key');
                    if (r.success) { alert('✅ Serper API key saved!'); location.reload(); }
                    else alert('Error: '+(r.data||'Unknown'));
                });
            });

            // ── Load all bots into memory ──
            $.post(A, {action:'dba_sniper_get_bots', nonce:N}, function(r){
                if (!r.success) return;
                BOTS = r.data;
                populateBotDropdown();
            });

            function populateBotDropdown() {
                var sel = $('#sniper-bot');
                sel.empty().append('<option value="">— Select a bot —</option>');
                $.each(BOTS, function(id, b){
                    var status = (b.status==='active') ? '' : ' [not loaded]';
                    var wired  = b.wired ? '' : ' ⏳';
                    sel.append('<option value="'+id+'"'+(b.status!=='active'?' disabled':'')+'>'+b.short+status+wired+' ('+Object.keys(b.themes||{}).length+' themes)</option>');
                });
            }

            // ── When bot changes → populate theme dropdown ──
            $('#sniper-bot').on('change', function(){
                var botId = $(this).val();
                var tsel = $('#sniper-theme').empty();
                if (!botId || !BOTS[botId]) {
                    tsel.append('<option value="">— select bot first —</option>');
                    return;
                }
                var themes = BOTS[botId].themes || {};
                tsel.append('<option value="">— Select theme —</option>');
                $.each(themes, function(slug, label){
                    tsel.append('<option value="'+slug+'">'+label+'</option>');
                });
            });

            // ── Auto-resolve: suggest best bot + theme when keyword changes ──
            function autoResolve() {
                var kw = $('#sniper-kw').val().trim(), lang = $('#sniper-lang').val();
                if (!kw || kw.length < 2) { $('#sniper-route-info').html(''); return; }
                $.post(A, {action:'dba_sniper_resolve', nonce:N, keyword:kw, language:lang}, function(r){
                    if (r.success && r.data) {
                        var d = r.data;
                        // Auto-select the bot
                        if (BOTS[d.bot_id]) {
                            $('#sniper-bot').val(d.bot_id).trigger('change');
                            // Auto-select the theme after dropdown populates
                            setTimeout(function(){ $('#sniper-theme').val(d.theme_slug); }, 50);
                        }
                        var wiredBadge = d.wired
                            ? '<span style="background:#dcfce7;color:#166534;padding:2px 8px;border-radius:3px;font-size:11px">✅ Wired</span>'
                            : '<span style="background:#fef3c7;color:#92400e;padding:2px 8px;border-radius:3px;font-size:11px">⏳ Not wired yet</span>';
                        $('#sniper-route-info').html(
                            '<div style="background:#f0f9ff;border:1px solid #bae6fd;padding:8px 14px;border-radius:6px;font-size:13px;margin-top:4px">'+
                            '🎯 <strong>Auto-detected:</strong> '+d.bot_label+' → "'+d.theme_label+'" ('+d.lang.toUpperCase()+') '+wiredBadge+
                            '<span style="color:#888;margin-left:10px;font-size:11px">score: '+d.score+' — you can override above</span>'+
                            '</div>'
                        );
                    } else {
                        $('#sniper-route-info').html(
                            '<div style="background:#fef2f2;color:#991b1b;padding:8px 14px;border-radius:6px;font-size:13px;margin-top:4px">'+
                            '⚠️ '+(r.data||'No matching bot/theme found — pick manually from the dropdowns above, or add the theme to a registry.')+
                            '</div>'
                        );
                    }
                });
            }
            $('#sniper-kw').on('input', function(){ clearTimeout(resolveTimer); resolveTimer = setTimeout(autoResolve, 600); });
            $('#sniper-lang').on('change', function(){ clearTimeout(resolveTimer); resolveTimer = setTimeout(autoResolve, 300); });

            function showProgress(pct, msg) {
                $('#sniper-progress').slideDown();
                $('#sniper-bar').css('width', pct+'%').text(pct+'%').css('background','linear-gradient(90deg,#2563eb,#7c3aed)');
                $('#sniper-status').text(msg);
            }

            function renderAnalysis(data) {
                var h = '<div style="background:#f0fdf4;border:1px solid #86efac;border-radius:8px;padding:16px;margin-top:10px">';
                h += '<h3 style="margin:0 0 10px;color:#166534">✅ Analysis: "'+data.keyword+'" ('+data.language.toUpperCase()+')</h3>';

                if (data.our_position > 0) {
                    h += '<p><strong>Our position:</strong> #'+data.our_position+' <a href="'+data.our_url+'" target="_blank">→</a></p>';
                } else {
                    h += '<p style="color:#991b1b"><strong>Not ranking</strong> — this post will be the entry point.</p>';
                }

                var m = data.metrics || {};
                var filteredCount = (data.filtered_out||[]).length;
                var compCount = (data.competitors||[]).length;

                h += '<div style="display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin:12px 0">';
                h += '<div style="background:#fff;padding:8px;border-radius:4px;text-align:center"><div style="font-size:20px;font-weight:bold;color:#2563eb">'+m.target_word_count+'</div><div style="font-size:11px;color:#666">Target Words</div></div>';
                h += '<div style="background:#fff;padding:8px;border-radius:4px;text-align:center"><div style="font-size:20px;font-weight:bold;color:#7c3aed">'+m.avg_keyword_density+'%</div><div style="font-size:11px;color:#666">Target Density</div></div>';
                h += '<div style="background:#fff;padding:8px;border-radius:4px;text-align:center"><div style="font-size:20px;font-weight:bold;color:#059669">'+m.target_h2_count+'</div><div style="font-size:11px;color:#666">Target H2s</div></div>';
                h += '<div style="background:#fff;padding:8px;border-radius:4px;text-align:center"><div style="font-size:20px;font-weight:bold;color:#166534">'+compCount+'</div><div style="font-size:11px;color:#666">Relevant</div></div>';
                h += '<div style="background:#fff;padding:8px;border-radius:4px;text-align:center"><div style="font-size:20px;font-weight:bold;color:#dc2626">'+filteredCount+'</div><div style="font-size:11px;color:#666">Filtered Out</div></div>';
                h += '</div>';

                // ── Relevant competitors table with relevance scores ──
                if (data.competitors && data.competitors.length) {
                    h += '<h4 style="margin:14px 0 6px;color:#166534">✅ Relevant Competitors (used for analysis)</h4>';
                    h += '<table class="widefat" style="font-size:12px;margin:6px 0"><thead><tr><th>#</th><th>Domain</th><th>Relevance</th><th>Words</th><th>H2s</th><th>KW%</th><th>FAQ</th><th>Table</th></tr></thead><tbody>';
                    data.competitors.forEach(function(c) {
                        var score = c.relevance_score || 0;
                        var scoreColor = score >= 60 ? '#059669' : score >= 40 ? '#2563eb' : '#f59e0b';
                        var scoreLabel = c.relevance_label || '';
                        h += '<tr><td>'+c.position+'</td><td><strong>'+c.domain+'</strong></td>';
                        h += '<td><span style="background:'+scoreColor+'15;color:'+scoreColor+';padding:2px 8px;border-radius:3px;font-weight:600;font-size:11px" title="'+scoreLabel+'">'+score+'</span></td>';
                        h += '<td>'+c.word_count+'</td><td>'+(c.headings.h2||[]).length+'</td><td>'+c.keyword_density+'%</td><td>'+(c.has_faq?'✓':'—')+'</td><td>'+(c.has_table?'✓':'—')+'</td></tr>';
                    });
                    h += '</tbody></table>';
                }

                // ── Filtered out domains ──
                if (data.filtered_out && data.filtered_out.length) {
                    h += '<details style="margin:10px 0;background:#fef2f2;border:1px solid #fecaca;border-radius:6px;padding:8px 12px">';
                    h += '<summary style="cursor:pointer;font-weight:600;color:#991b1b;font-size:13px">🚫 Filtered Out — '+filteredCount+' irrelevant domain(s)</summary>';
                    h += '<table style="font-size:11px;margin:8px 0;width:100%"><thead><tr style="color:#888"><th>#</th><th>Domain</th><th>Score</th><th>Reason</th></tr></thead><tbody>';
                    data.filtered_out.forEach(function(f) {
                        h += '<tr style="color:#999"><td>'+f.position+'</td><td>'+f.domain+'</td><td>'+f.score+'</td><td>'+f.reason+'</td></tr>';
                    });
                    h += '</tbody></table></details>';
                }

                if (data.heading_union && data.heading_union.length) {
                    h += '<details style="margin:8px 0"><summary style="cursor:pointer;font-weight:600">📋 Heading Topics ('+data.heading_union.length+')</summary><ul style="margin:8px 0;font-size:13px">';
                    data.heading_union.forEach(function(hu) { h += '<li>'+hu.heading+' <span style="color:#888">('+hu.frequency+'x)</span></li>'; });
                    h += '</ul></details>';
                }

                if (data.structural_advantages && data.structural_advantages.length) {
                    h += '<details style="margin:8px 0"><summary style="cursor:pointer;font-weight:600">💡 Exploitable Weaknesses</summary><ul style="margin:8px 0;font-size:13px">';
                    data.structural_advantages.forEach(function(a) { h += '<li><strong>'+a.label+'</strong>: '+a.detail+'</li>'; });
                    h += '</ul></details>';
                }

                h += '</div>';
                $('#sniper-results').html(h).slideDown();
                $('#sniper-generate').show();
            }

            // ── Analyze ──
            $('#sniper-analyze').on('click', function(){
                var kw = $('#sniper-kw').val().trim(), lang = $('#sniper-lang').val();
                if (!kw) { alert('Enter a keyword.'); return; }
                var B = $(this).prop('disabled',1).html('⏳ Crawling...');
                showProgress(10, '🔍 Crawling Google top 20 for "'+kw+'"...');
                $.ajax({
                    url: A, method: 'POST', timeout: 120000,
                    data: {action:'dba_sniper_analyze', nonce:N, keyword:kw, language:lang},
                    success: function(r) {
                        B.prop('disabled',0).html('🔍 Analyze Competitors');
                        if (r.success && r.data) {
                            showProgress(100, '✅ Analysis complete — '+(r.data.competitors||[]).length+' competitors analyzed');
                            renderAnalysis(r.data);
                        } else {
                            showProgress(100, '❌ ' + (r.data || 'Analysis failed'));
                            $('#sniper-bar').css('background','#dc2626');
                        }
                    },
                    error: function(x) {
                        B.prop('disabled',0).html('🔍 Analyze Competitors');
                        showProgress(100, '❌ '+x.statusText);
                        $('#sniper-bar').css('background','#dc2626');
                    }
                });
            });

            // ── Generate (sends chosen bot + theme + language) ──
            $('#sniper-generate').on('click', function(){
                var kw = $('#sniper-kw').val().trim(), lang = $('#sniper-lang').val();
                var botId = $('#sniper-bot').val(), theme = $('#sniper-theme').val();
                if (!kw) { alert('Enter a keyword.'); return; }
                if (!botId) { alert('Select a bot from the dropdown.'); return; }
                if (!theme) { alert('Select a theme from the dropdown.'); return; }
                var botLabel = BOTS[botId] ? BOTS[botId].short : botId;
                if (!confirm('This will:\n1. Crawl Google top 20 for "'+kw+'"\n2. Analyze competitors\n3. Feed intelligence into '+botLabel+' → "'+theme+'"\n4. Generate an optimized post\n\nProceed?')) return;
                var B = $(this).prop('disabled',1).html('⏳ Routing to '+botLabel+'...');
                showProgress(20, '🎯 Crawling + analyzing + routing to '+botLabel+'...');
                $.ajax({
                    url: A, method: 'POST', timeout: 300000,
                    data: {action:'dba_sniper_generate', nonce:N, keyword:kw, language:lang, bot_id:botId, theme_slug:theme},
                    success: function(r) {
                        B.prop('disabled',0).html('🚀 Generate Post');
                        if (r.success && r.data) {
                            showProgress(100, '✅ '+r.data.message);
                            $('#sniper-bar').css('background','linear-gradient(90deg,#059669,#34d399)');
                            if (r.data.edit_url) {
                                $('#sniper-status').append(' — <a href="'+r.data.edit_url+'" target="_blank" style="color:#fff;text-decoration:underline">Edit Post →</a>');
                            }
                            setTimeout(function(){ location.reload(); }, 4000);
                        } else {
                            showProgress(100, '❌ '+(r.data||'Generation failed'));
                            $('#sniper-bar').css('background','#dc2626');
                        }
                    },
                    error: function(x) {
                        B.prop('disabled',0).html('🚀 Generate Post');
                        showProgress(100, '❌ '+x.statusText);
                        $('#sniper-bar').css('background','#dc2626');
                    }
                });
            });

            // ── Save keyword (with bot/theme from dropdowns) ──
            $('#sniper-save-kw').on('click', function(){
                var kw = $('#sniper-kw').val().trim(), lang = $('#sniper-lang').val();
                var botId = $('#sniper-bot').val() || '', theme = $('#sniper-theme').val() || '';
                if (!kw) { alert('Enter a keyword.'); return; }
                var btn = $(this).prop('disabled',1).html('⏳ Saving...');
                $.post(A, {action:'dba_sniper_add_keyword', nonce:N, keyword:kw, language:lang, bot_id:botId, theme_slug:theme}, function(r){
                    btn.prop('disabled',0).html('💾 Save Keyword');
                    if (r.success) {
                        var msg = '✅ Keyword "'+kw+'" saved';
                        if (r.data.bot_id) msg += ' → '+r.data.bot_id+' / '+r.data.theme_slug;
                        alert(msg);
                        location.reload();
                    } else {
                        alert('Error: '+(r.data||'Unknown'));
                    }
                });
            });

            // ── Delete keyword ──
            $(document).on('click', '.sniper-del', function(){
                if (!confirm('Remove this keyword?')) return;
                var key = $(this).data('key'), row = $(this).closest('tr');
                $.post(A, {action:'dba_sniper_del_keyword', nonce:N, kw_key:key}, function(r){
                    if (r.success) row.fadeOut();
                });
            });

            // ── Re-analyze from table ──
            $(document).on('click', '.sniper-re-analyze', function(){
                var kw = $(this).data('kw'), lang = $(this).data('lang');
                var bot = $(this).data('bot'), theme = $(this).data('theme');
                $('#sniper-kw').val(kw);
                $('#sniper-lang').val(lang).trigger('change');
                if (bot) setTimeout(function(){ $('#sniper-bot').val(bot).trigger('change'); if(theme) setTimeout(function(){ $('#sniper-theme').val(theme); },300); },500);
                setTimeout(function(){ $('html,body').animate({scrollTop:$('#sniper-analyze').offset().top-100},300); $('#sniper-analyze').trigger('click'); }, 1000);
            });

            // ── GENERATE FROM TABLE — PROGRESS MODAL WITH REAL SERVER POLLING ──
            var pollTimer = null;

            function showGenModal(kw, bot, theme) {
                $('#sniper-gen-modal').css('display','flex');
                $('#gen-modal-title').html('🚀 Generating: <strong>"'+kw+'"</strong> → '+bot+' → '+theme);
                $('#gen-modal-bar').css({width:'0%', background:'linear-gradient(90deg,#2563eb,#7c3aed)'});
                $('#gen-modal-result').hide().html('');
                $('#gen-modal-steps').html('<div style="color:#64748b;font-size:13px">Starting pipeline...</div>');
                $('#gen-modal-status').text('Initializing...');

                // Start polling server for real progress
                pollTimer = setInterval(function(){
                    $.post(A, {action:'dba_sniper_progress', nonce:N}, function(r){
                        if (r.success && r.data) {
                            var p = r.data;
                            $('#gen-modal-bar').css('width', p.pct+'%');
                            $('#gen-modal-status').text(p.label || 'Working...');
                            if (p.detail) {
                                var stepHtml = '<div style="color:#1e40af;font-size:13px;font-weight:600;padding:2px 0">'+p.label+'</div>';
                                if (p.detail) stepHtml += '<div style="color:#64748b;font-size:12px;padding:0 0 4px">'+p.detail+'</div>';
                                // Append, don't replace — shows history
                                var existing = $('#gen-modal-steps').html();
                                var lastLabel = $('#gen-modal-steps').data('last');
                                if (lastLabel !== p.label) {
                                    // Mark previous as done
                                    if (lastLabel) {
                                        existing = existing.replace('color:#1e40af', 'color:#059669').replace('font-weight:600', 'font-weight:normal');
                                    }
                                    $('#gen-modal-steps').html(existing + stepHtml).data('last', p.label);
                                }
                            }
                        }
                    });
                }, 2000);
            }

            function endGenModal(success, data) {
                clearInterval(pollTimer);
                $('#gen-modal-bar').css({width:'100%', background: success ? 'linear-gradient(90deg,#059669,#34d399)' : '#dc2626'});
                $('#gen-modal-status').text(success ? '✅ Complete!' : '❌ Failed');

                var h = '';
                if (success) {
                    h += '<div style="background:#f0fdf4;border:2px solid #059669;border-radius:8px;padding:16px">';
                    h += '<div style="font-size:18px;margin-bottom:10px">✅ Post #'+data.post_id+' Created</div>';
                    h += '<p style="margin:4px 0;font-size:13px">'+data.message+'</p>';

                    // Verification checklist
                    var v = data.verification || {};
                    if (v.checks) {
                        h += '<div style="margin:12px 0;padding:10px;background:#fff;border-radius:6px;border:1px solid #e2e8f0">';
                        h += '<div style="font-weight:bold;font-size:13px;margin-bottom:6px">🔎 Post Verification ('+v.pass_count+'/'+v.total+')</div>';
                        $.each(v.checks, function(key, c){
                            var icon = c.pass ? '✅' : '❌';
                            var color = c.pass ? '#059669' : '#dc2626';
                            h += '<div style="font-size:12px;padding:2px 0;color:'+color+'">'+icon+' <strong>'+c.label+'</strong>: '+c.detail+'</div>';
                        });
                        h += '</div>';
                    }

                    // Self-plagiarism result
                    var sp = v.self_plagiarism || {};
                    if (sp.status) {
                        var spColor = sp.status === 'pass' ? '#059669' : '#dc2626';
                        var spIcon = sp.status === 'pass' ? '✅' : '⚠️';
                        h += '<div style="margin:8px 0;padding:8px;background:'+(sp.status==='pass'?'#f0fdf4':'#fef2f2')+';border-radius:4px;font-size:12px;color:'+spColor+'">';
                        h += spIcon+' <strong>Self-Plagiarism Gate C:</strong> '+sp.reason;
                        if (sp.comparisons && sp.comparisons.length) {
                            h += '<div style="margin-top:4px;color:#666">';
                            sp.comparisons.forEach(function(c){ h += c.similarity+'% vs #'+c.post_id+' "'+c.title.substring(0,40)+'..." | '; });
                            h += '</div>';
                        }
                        h += '</div>';
                    }

                    h += '<div style="margin-top:12px">';
                    if (data.edit_url) h += '<a href="'+data.edit_url+'" target="_blank" style="display:inline-block;background:#2563eb;color:#fff;padding:10px 24px;border-radius:6px;text-decoration:none;font-weight:bold;margin-right:8px">✏️ Edit Post</a>';
                    h += '<button onclick="location.reload()" style="background:#059669;color:#fff;padding:10px 24px;border-radius:6px;border:none;font-weight:bold;cursor:pointer">🔄 Refresh</button>';
                    h += '</div></div>';
                } else {
                    h += '<div style="background:#fef2f2;border:2px solid #dc2626;border-radius:8px;padding:16px">';
                    h += '<div style="font-size:18px;margin-bottom:8px">❌ Generation Failed</div>';
                    h += '<p style="font-size:13px;color:#991b1b">'+(typeof data === 'string' ? data : (data.message || 'Unknown error'))+'</p>';
                    h += '<button onclick="$(\'#sniper-gen-modal\').hide()" style="margin-top:10px;background:#666;color:#fff;padding:8px 20px;border-radius:6px;border:none;cursor:pointer">Close</button>';
                    h += '</div>';
                }
                $('#gen-modal-result').html(h).show();
            }

            $(document).on('click', '.sniper-re-generate', function(){
                var kw = $(this).data('kw'), lang = $(this).data('lang');
                var bot = $(this).data('bot'), theme = $(this).data('theme');
                var btn = $(this);

                if (!bot || !theme) { alert('No bot/theme assigned.\nClick 🔍 first to analyze, then use 🚀.'); return; }
                if (!confirm('Generate SEO-optimized post for "'+kw+'"?\n\nBot: '+bot+'\nTheme: '+theme+'\nLang: '+lang.toUpperCase()+'\n\nPipeline: Crawl → Analyze → Filter → Brief → GPT-4 → Validate → Plagiarism A+B → Self-Plagiarism C → DALL-E → Yoast → Publish\n\nThis takes 1-3 minutes.')) return;

                btn.prop('disabled',1).html('⏳');
                showGenModal(kw, bot, theme);

                $.ajax({
                    url: A, method: 'POST', timeout: 300000,
                    data: {action:'dba_sniper_generate', nonce:N, keyword:kw, language:lang, bot_id:bot, theme_slug:theme},
                    success: function(r) {
                        btn.prop('disabled',0).html('🚀');
                        if (r.success && r.data) {
                            endGenModal(true, r.data);
                        } else {
                            endGenModal(false, r.data || 'Unknown error');
                        }
                    },
                    error: function(x) {
                        btn.prop('disabled',0).html('🚀');
                        endGenModal(false, 'Request failed: '+x.statusText);
                    }
                });
            });

            // ── REPAIR POST (🔧 button) ──
            $(document).on('click', '.sniper-repair', function(){
                var btn = $(this), pid = btn.data('post-id');
                if (!confirm('Repair post #'+pid+'?\n\nThis will:\n• Check & regenerate DALL-E image if missing\n• Set Yoast SEO meta if missing\n• Tag with Sniper metadata')) return;
                btn.prop('disabled',1).html('⏳');
                $.ajax({
                    url: A, method: 'POST', timeout: 120000,
                    data: {action:'dba_sniper_repair', nonce:N, post_id:pid},
                    success: function(r) {
                        btn.prop('disabled',0).html('🔧');
                        if (r.success && r.data) {
                            var msgs = [];
                            $.each(r.data, function(k, v){
                                var icon = v.action === 'ok' ? '✅' : v.action === 'generated' || v.action === 'repaired' ? '🔧' : '⚠️';
                                msgs.push(icon+' '+k+': '+v.action+(v.detail ? ' — '+v.detail : '')+(v.error ? ' — '+v.error : ''));
                            });
                            alert('Repair Results for Post #'+pid+':\n\n'+msgs.join('\n'));
                            location.reload();
                        } else {
                            alert('Repair failed: '+(r.data||'Unknown'));
                        }
                    },
                    error: function(x) { btn.prop('disabled',0).html('🔧'); alert('Repair failed: '+x.statusText); }
                });
            });

            // ── Check single keyword rank ──
            $(document).on('click', '.sniper-check-rank', function(){
                var btn = $(this), kw = btn.data('kw'), lang = btn.data('lang'), key = btn.data('key');
                var cell = $('#row-'+key+' .rank-cell');
                btn.prop('disabled',1).html('⏳');
                cell.find('.sniper-error').remove(); // Clear previous error
                $.ajax({
                    url: A, method: 'POST', timeout: 60000,
                    data: {action:'dba_sniper_check_rank', nonce:N, keyword:kw, language:lang},
                    success: function(r) {
                        btn.prop('disabled',0).html('📍');
                        if (r.success && r.data) {
                            var d = r.data, t = d.trend || {};
                            var posHtml = d.position > 0
                                ? '<span style="background:'+(d.position<=3?'#dcfce7':d.position<=10?'#dbeafe':'#fef2f2')+';color:'+(d.position<=3?'#166534':d.position<=10?'#1e40af':'#991b1b')+';padding:3px 10px;border-radius:4px;font-weight:bold;font-size:15px">#'+d.position+'</span>'
                                : '<span style="color:#999;font-size:13px">Not ranked</span>';
                            var trendHtml = '<span style="color:'+(t.color||'#888')+';font-size:13px;margin-left:6px">'+
                                (t.arrow||'—')+' <small>'+(t.label||'')+'</small></span>';
                            cell.html(posHtml + trendHtml);
                        } else {
                            cell.find('.sniper-error').remove();
                            cell.append(' <span class="sniper-error" style="color:#dc2626;font-size:11px" title="'+(r.data||'Unknown error')+'">⚠ '+(r.data||'Error').substring(0,40)+'</span>');
                        }
                    },
                    error: function(x) {
                        btn.prop('disabled',0).html('📍');
                        cell.find('.sniper-error').remove();
                        cell.append(' <span class="sniper-error" style="color:#dc2626;font-size:11px">⚠ '+x.statusText+'</span>');
                    }
                });
            });

            // ── Check ALL ranks ──
            $('#sniper-check-all-ranks').on('click', function(){
                var kwCount = $('table.widefat tbody tr').length;
                if (!kwCount) { alert('No keywords to check.'); return; }
                if (!confirm('Check Google rank for '+kwCount+' keyword(s).\nTakes 3-5 seconds each ('+Math.round(kwCount*4)+' sec total).\n\nProceed?')) return;
                var btn = $(this).prop('disabled',1).html('⏳ Checking (0/'+kwCount+')...');
                $.ajax({
                    url: A, method: 'POST', timeout: 300000,
                    data: {action:'dba_sniper_check_rank_all', nonce:N},
                    success: function(r) {
                        btn.prop('disabled',0).html('🔄 Check All Ranks Now');
                        if (r.success && r.data) {
                            var d = r.data, results = d.results || {};
                            var ok=0, fail=0, msgs=[];
                            $.each(results, function(key, res){
                                if (res.error) {
                                    fail++;
                                    msgs.push(res.keyword+': ⚠ '+res.error);
                                } else {
                                    ok++;
                                    var pos = res.position > 0 ? '#'+res.position : 'not ranked';
                                    var trend = (res.trend||{}).label || '';
                                    msgs.push(res.keyword+': '+pos+' '+trend);
                                }
                            });
                            alert('Checked '+d.checked+' keywords:\n✅ '+ok+' ok, ❌ '+fail+' errors\n\n'+msgs.join('\n'));
                            location.reload();
                        } else {
                            alert('Error: '+(r.data||'Unknown'));
                        }
                    },
                    error: function(x) {
                        btn.prop('disabled',0).html('🔄 Check All Ranks Now');
                        alert('Request failed: '+x.statusText+'\n\nThis usually means the request timed out. Try checking fewer keywords or wait 1-2 hours if Google rate-limited you.');
                    }
                });
            });

            // ═══ TIS IMPORT HANDLERS ═══

            // Import ALL TIS keywords
            $('#sniper-import-all-tis').on('click', function(){
                var btn = $(this).prop('disabled',true).text('Importing...');
                $.post(A, {action:'dba_sniper_import_tis', nonce:N, mode:'all'}, function(r){
                    btn.prop('disabled',false).html('⚡ Import All to Tracker');
                    if (r.success) {
                        alert('✅ Imported ' + r.data.imported + ' keywords (' + r.data.skipped + ' already tracked). Total: ' + r.data.total);
                        location.reload();
                    } else {
                        alert('Error: ' + (r.data || 'Unknown'));
                    }
                });
            });

            // Import SINGLE TIS keyword
            $(document).on('click', '.sniper-import-tis-one', function(){
                var btn = $(this), kw = btn.data('kw');
                btn.prop('disabled',true).text('...');
                $.post(A, {action:'dba_sniper_import_tis', nonce:N, mode:'selected', 'keywords[]':kw}, function(r){
                    if (r.success && r.data.imported > 0) {
                        btn.replaceWith('<span style="color:#059669;font-weight:600">✓ Tracked</span>');
                    } else {
                        btn.prop('disabled',false).text('+ Track');
                        if (r.data && r.data.skipped > 0) {
                            btn.replaceWith('<span style="color:#059669;font-weight:600">✓ Already tracked</span>');
                        }
                    }
                });
            });
        });
        </script>
        <?php
    }
}
