<?php
/**
 * DBA AJAX - Handles AJAX requests for admin operations
 */
class DBA_AJAX {

    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('wp_ajax_dba_refresh_sitemap', array($this, 'ajax_refresh_sitemap'));
        add_action('wp_ajax_dba_get_logs', array($this, 'ajax_get_logs'));
        add_action('wp_ajax_dba_test_openai', array($this, 'ajax_test_openai'));
        add_action('wp_ajax_dba_get_status', array($this, 'ajax_get_status'));
        add_action('wp_ajax_dba_clear_logs', array($this, 'ajax_clear_logs'));
        add_action('wp_ajax_dba_check_plagiarism', array($this, 'ajax_check_plagiarism'));
        add_action('wp_ajax_dba_extract_headline', array($this, 'ajax_extract_headline'));
    }

    /**
     * Extract headline from a news URL (anonymous fetch with browser UA)
     * Fallback: extract from URL slug if the site blocks server requests
     */
    public function ajax_extract_headline() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $url = esc_url_raw($_POST['url'] ?? '');
        if (empty($url)) {
            wp_send_json_error(array('message' => 'No URL provided'));
        }

        $headline = '';
        $source = '';

        // ATTEMPT 1: Fetch the page with browser-like headers
        $response = wp_remote_get($url, array(
            'timeout'     => 15,
            'redirection' => 5,
            'user-agent'  => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
            'headers'     => array(
                'Accept'          => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                'Accept-Language' => 'en-US,en;q=0.9',
            ),
        ));

        if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
            $html = wp_remote_retrieve_body($response);
            if (!empty($html)) {
                // Priority 1: og:title (most reliable)
                if (preg_match('/<meta[^>]+property=["\']og:title["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $m)) {
                    $headline = $m[1]; $source = 'og:title';
                }
                // Also try content before property (some sites reverse attr order)
                elseif (preg_match('/<meta[^>]+content=["\']([^"\']+)["\'][^>]+property=["\']og:title["\']/i', $html, $m)) {
                    $headline = $m[1]; $source = 'og:title';
                }
                // Priority 2: twitter:title
                elseif (preg_match('/<meta[^>]+name=["\']twitter:title["\'][^>]+content=["\']([^"\']+)["\']/i', $html, $m)) {
                    $headline = $m[1]; $source = 'twitter:title';
                }
                elseif (preg_match('/<meta[^>]+content=["\']([^"\']+)["\'][^>]+name=["\']twitter:title["\']/i', $html, $m)) {
                    $headline = $m[1]; $source = 'twitter:title';
                }
                // Priority 3: <title> tag
                elseif (preg_match('/<title[^>]*>([^<]+)<\/title>/i', $html, $m)) {
                    $headline = $m[1]; $source = 'title tag';
                }
                // Priority 4: first <h1>
                elseif (preg_match('/<h1[^>]*>(.*?)<\/h1>/si', $html, $m)) {
                    $headline = wp_strip_all_tags($m[1]); $source = 'h1';
                }
            }
        }

        // ATTEMPT 2: Fallback — extract from URL slug
        if (empty($headline)) {
            $path = parse_url($url, PHP_URL_PATH);
            if (!empty($path)) {
                // Get last meaningful path segment (the article slug)
                $segments = array_filter(explode('/', trim($path, '/')));
                $slug = end($segments);
                if (!empty($slug) && strlen($slug) > 5) {
                    // Convert slug to title: "crypto-startup-erebor-becomes-first-bank" → "Crypto Startup Erebor Becomes First Bank"
                    $headline = ucwords(str_replace(array('-', '_'), ' ', $slug));
                    // Remove common trailing patterns like dates or IDs
                    $headline = preg_replace('/\s+\d{6,}$/', '', $headline);
                    $source = 'url-slug';
                }
            }
        }

        if (empty($headline)) {
            wp_send_json_error(array('message' => 'Could not extract headline. Try entering it manually in News Headline field.'));
        }

        // Clean up: decode entities, trim site name suffixes
        $headline = html_entity_decode($headline, ENT_QUOTES, 'UTF-8');
        $headline = preg_replace('/\s*[\|–—\-:]\s*(NY Post|New York Post|Reuters|Bloomberg|Financial Times|FT|CNBC|BBC|CNN|WSJ|Wall Street Journal|The Guardian|Forbes|Business Insider|TechCrunch|The Verge|AP News|Associated Press|The New York Times|NYT|Washington Post|POLITICO|Axios|Wired|The Hill|MarketWatch|Barron\'s|Seeking Alpha|CoinDesk|Decrypt|The Block)\s*$/i', '', $headline);
        $headline = trim($headline);

        // Get today's 3-letter day abbreviation
        $today_day = strtolower(gmdate('D', current_time('timestamp')));
        $day_map = array('mon' => 'Mon', 'tue' => 'Tue', 'wed' => 'Wed', 'thu' => 'Thu', 'fri' => 'Fri', 'sat' => 'Sat', 'sun' => 'Sun');
        $today_label = isset($day_map[$today_day]) ? $day_map[$today_day] : ucfirst($today_day);

        error_log('DBA Extract: "' . $headline . '" (source: ' . $source . ')');

        wp_send_json_success(array(
            'headline'  => $headline,
            'today_day' => $today_label,
            'source'    => $source,
        ));
    }

    /**
     * Manual plagiarism check on existing post
     */
    public function ajax_check_plagiarism() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
        if (!$post_id) {
            wp_send_json_error(array('message' => 'No post ID provided'));
        }

        $content = get_post_field('post_content', $post_id);
        if (empty($content)) {
            wp_send_json_error(array('message' => 'Post has no content'));
        }

        $checker = DBA_Plagiarism::get_instance();
        $result = $checker->check($content, $post_id);

        // Store result
        update_post_meta($post_id, '_dba_plagiarism_score', $result['score']);
        update_post_meta($post_id, '_dba_plagiarism_method', $result['method']);
        update_post_meta($post_id, '_dba_plagiarism_checked', current_time('mysql'));

        wp_send_json_success(array(
            'pass'    => $result['pass'],
            'score'   => $result['score'],
            'method'  => $result['method'],
            'details' => $result['details'],
            'message' => $result['pass']
                ? 'Plagiarism check PASSED — ' . $result['score'] . '% unique (' . $result['method'] . ')'
                : 'Plagiarism check FAILED — ' . $result['score'] . '% unique (' . $result['method'] . ')',
        ));
    }

    /**
     * Refresh sitemap registry
     */
    public function ajax_refresh_sitemap() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $sitemap = DBA_Sitemap::get_instance();

        try {
            $registry = $sitemap->refresh_registry();
            $full = $sitemap->get_full_registry();
        } catch (\Throwable $e) {
            wp_send_json_error(array(
                'message' => 'Sitemap refresh failed: ' . $e->getMessage() . '. Check if your server can reach your sitemap URL.'
            ));
            return;
        }

        if (empty($registry) && empty($full)) {
            wp_send_json_error(array(
                'message' => 'Sitemap returned 0 pages. Your server may be blocking outbound HTTP to itself. Try: 1) Check sitemap URL in settings, 2) Visit the sitemap URL in a browser to confirm it works, 3) Ask your host to whitelist loopback HTTP requests.'
            ));
            return;
        }

        wp_send_json_success(array(
            'message' => 'Sitemap refreshed: ' . count($full) . ' total pages, ' . count($registry) . ' blog URLs — inbound links ready',
            'count'   => count($registry),
            'full_count' => count($full),
        ));
    }

    /**
     * Get generation logs
     */
    public function ajax_get_logs() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $limit = isset($_POST['limit']) ? intval($_POST['limit']) : 50;
        $logger = DBA_Logger::get_instance();
        $logs = $logger->get_logs($limit);

        wp_send_json_success(array('logs' => $logs));
    }

    /**
     * Test OpenAI connection
     */
    public function ajax_test_openai() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $settings = get_option('dba_settings', array());
        $api_key = isset($settings['openai_api_key']) ? $settings['openai_api_key'] : '';

        if (empty($api_key)) {
            wp_send_json_error(array('message' => 'No API key configured'));
        }

        $model = $settings['openai_model'] ?? 'gpt-4.1';
        $last_code = 0;

        // Try up to 3 times with backoff for 429
        for ($attempt = 0; $attempt < 3; $attempt++) {
            if ($attempt > 0) {
                sleep(min(pow(2, $attempt) * 5, 30)); // 5s, 10s, 20s
            }

            $response = wp_remote_post('https://api.openai.com/v1/chat/completions', array(
                'timeout' => 30,
                'headers' => array(
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type'  => 'application/json',
                ),
                'body' => json_encode(array(
                    'model'      => $model,
                    'messages'   => array(array('role' => 'user', 'content' => 'Say "Connection OK" in 3 words.')),
                    'max_tokens' => 20,
                )),
            ));

            if (is_wp_error($response)) {
                wp_send_json_error(array('message' => 'Connection failed: ' . $response->get_error_message()));
            }

            $last_code = wp_remote_retrieve_response_code($response);

            if ($last_code === 200) {
                $result = json_decode(wp_remote_retrieve_body($response), true);
                $reply = isset($result['choices'][0]['message']['content']) ? $result['choices'][0]['message']['content'] : 'OK';
                wp_send_json_success(array(
                    'message' => 'OpenAI connection successful: ' . $reply,
                    'model'   => $model,
                ));
                return;
            }

            // If not 429, don't retry
            if ($last_code !== 429) {
                break;
            }
        }

        // Error messages by status code
        $body_text = wp_remote_retrieve_body($response);
        $parsed = json_decode($body_text, true);
        $api_msg = isset($parsed['error']['message']) ? $parsed['error']['message'] : '';

        if ($last_code === 429) {
            $msg = "Rate limit (429). Your OpenAI account is hitting its request limit.\n\n";
            $msg .= "Fix: Go to https://platform.openai.com/settings/organization/billing and check:\n";
            $msg .= "1. You have credits remaining\n";
            $msg .= "2. Your payment method is active\n";
            $msg .= "3. You are not on the free tier (very low limits)\n";
            if ($api_msg) $msg .= "\nOpenAI says: " . $api_msg;
            wp_send_json_error(array('message' => $msg));
        } elseif ($last_code === 401) {
            wp_send_json_error(array('message' => 'Invalid API key (401). Check your key at https://platform.openai.com/api-keys'));
        } elseif ($last_code === 403) {
            wp_send_json_error(array('message' => 'Access denied (403). Your API key may not have access to model: ' . $model));
        } elseif ($last_code === 404) {
            wp_send_json_error(array('message' => 'Model not found (404). The model "' . $model . '" may not be available on your plan.'));
        } else {
            wp_send_json_error(array('message' => 'API error ' . $last_code . ': ' . substr($body_text, 0, 300)));
        }
    }

    /**
     * Get current status
     */
    public function ajax_get_status() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $logger = DBA_Logger::get_instance();
        $last_run = get_option('dba_last_run', array());
        $registry = get_option('dba_link_registry', array());

        wp_send_json_success(array(
            'today_posts'   => $logger->get_today_count(),
            'today_themes'  => $logger->get_today_themes(),
            'registry_size' => count($registry),
            'last_run'      => $last_run,
            'next_run'      => DBA_Scheduler::get_next_run_info(),
            'posting_days'  => DBA_Scheduler::get_posting_days_string(),
        ));
    }

    /**
     * Clear logs
     */
    public function ajax_clear_logs() {
        check_ajax_referer('dba_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        global $wpdb;
        $table = $wpdb->prefix . DBA_LOG_TABLE;
        $wpdb->query("TRUNCATE TABLE {$table}");

        wp_send_json_success(array('message' => 'Logs cleared'));
    }
}
