<?php

/**
 * Quick Internal Linking Metrics Endpoint
 * 
 * Provides immediate access to linking metrics without module dependencies
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\RestApi;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;

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


/**
 * Register quick metrics endpoint
 */


add_action('rest_api_init', function() {
    register_rest_route('prorank-seo/v1', '/linking/metrics', [
        [
            'methods' => WP_REST_Server::READABLE,
            'callback' => __NAMESPACE__ . '\get_quick_link_metrics',
            'permission_callback' => function() {
                return current_user_can('edit_posts');
            }
        ]
    ]);
    
    // Register the scan endpoint
    register_rest_route('prorank-seo/v1', '/linking/scan', [
        [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => __NAMESPACE__ . '\run_link_scan',
            'permission_callback' => function() {
                return current_user_can('edit_posts');
            },
            'args' => [
                'scan_type' => [
                    'default' => 'full',
                    'sanitize_callback' => 'sanitize_text_field',
                ],
            ],
        ]
    ]);
});

/**
 * Get link metrics quickly
 */
function get_quick_link_metrics(WP_REST_Request $request): WP_REST_Response {
    global $wpdb;

    $scan_history = get_option('prorank_internal_linking_scan_history', []);
    $latest_scan = (is_array($scan_history) && !empty($scan_history) && is_array($scan_history[0])) ? $scan_history[0] : null;

    if (is_array($latest_scan)) {
        $total_posts = max(0, (int) ($latest_scan['total_posts'] ?? 0));
        $total_internal_links = max(0, (int) ($latest_scan['total_internal_links'] ?? 0));
        $total_external_links = max(0, (int) ($latest_scan['total_external_links'] ?? 0));
        $orphaned_posts = max(0, (int) ($latest_scan['orphan_count'] ?? 0));
        $broken_links = max(0, (int) ($latest_scan['broken_links'] ?? 0));
        $posts_with_links = max(0, (int) ($latest_scan['posts_with_links'] ?? max(0, $total_posts - $orphaned_posts)));
        $link_coverage = round((float) ($latest_scan['link_coverage'] ?? 0), 2);
        $avg_links = isset($latest_scan['avg_links']) ? (float) $latest_scan['avg_links'] : ($posts_with_links > 0 ? ($total_internal_links + $total_external_links) / $posts_with_links : 0.0);
        $external_percentage = isset($latest_scan['external_percentage'])
            ? (float) $latest_scan['external_percentage']
            : (($total_internal_links + $total_external_links) > 0 ? ($total_external_links / ($total_internal_links + $total_external_links)) * 100 : 0.0);

        // Keep scoring deterministic from snapshot data.
        $link_quality_score = 0;
        if ($link_coverage > 0) {
            $link_quality_score += min(50, $link_coverage / 2);
        }
        if ($avg_links >= 3 && $avg_links <= 8) {
            $link_quality_score += 50;
        } elseif ($avg_links >= 2 && $avg_links <= 12) {
            $link_quality_score += 35;
        } elseif ($avg_links >= 1) {
            $link_quality_score += 20;
        }
        $link_quality_score = min(100, max(0, (int) round($link_quality_score)));

        // Derive a sane anchor score from average links/post until deep anchor analysis runs.
        $anchor_length_score = $avg_links >= 2 ? 70 : 50;

        // Link clicks if table exists.
        $click_count = 0;
        $clicks_table = $wpdb->prefix . 'prorank_link_clicks';
        if ($wpdb->get_var("SHOW TABLES LIKE '$clicks_table'") === $clicks_table) {
            $click_count = (int) ($wpdb->get_var("SELECT COUNT(*) FROM $clicks_table") ?: 0);
        }

        return rest_ensure_response([
            'success' => true,
            'data' => [
                'posts_crawled' => $total_posts,
                'link_clicks' => $click_count,
                'orphaned_posts' => $orphaned_posts,
                'broken_links' => $broken_links,
                'link_coverage' => $link_coverage,
                'link_quality_score' => $link_quality_score,
                'external_site_focus' => round($external_percentage, 0),
                'anchor_length_score' => $anchor_length_score,
                'total_internal_links' => $total_internal_links,
                'average_links_per_post' => round($avg_links, 1),
                'posts_without_links' => $orphaned_posts,
                'most_linked_domains' => [],
                'recent_broken_links' => [],
                'ai_enabled' => class_exists('\ProRank\SEO\AI\Manager'),
                'gsc_connected' => !empty(get_option('prorank_seo_gsc_property', '')),
                'data_source' => 'scan_history',
            ],
        ]);
    }
    
    // Get post counts
    $post_count = wp_count_posts('post');
    $page_count = wp_count_posts('page');
    $total_posts = ($post_count->publish ?? 0) + ($page_count->publish ?? 0);
    
    // Get REAL orphan count more efficiently
    $all_posts = $wpdb->get_results(
        "SELECT ID, post_title, post_name FROM {$wpdb->posts} 
        WHERE post_status = 'publish' 
        AND post_type IN ('post', 'page')
        LIMIT 100",  // Limit to prevent timeout
        ARRAY_A
    );
    
    $orphan_meta_count = 0;
    
    // Use more efficient approach - check if posts have links pointing to them
    if (!empty($all_posts)) {
        $post_ids = array_column($all_posts, 'ID');
        $placeholders = implode(',', array_fill(0, count($post_ids), '%d'));
        
        // Get all posts that have at least one internal link pointing to them
        $linked_posts = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT pm.meta_value 
                FROM {$wpdb->postmeta} pm
                WHERE pm.meta_key = %s
                AND pm.meta_value IN ($placeholders)",
                array_merge(['_prorank_linked_to'], $post_ids)
            )
        );
        
        // If no meta exists, do a quick sample check
        if (empty($linked_posts)) {
            // Quick estimate based on sample
            $sample_size = min(10, count($all_posts));
            for ($i = 0; $i < $sample_size; $i++) {
                $post = $all_posts[$i];
                $permalink = get_permalink($post['ID']);
                $has_link = $wpdb->get_var($wpdb->prepare(
                    "SELECT 1 FROM {$wpdb->posts} 
                    WHERE post_status = 'publish' 
                    AND ID != %d
                    AND post_content LIKE %s
                    LIMIT 1",
                    $post['ID'],
                    '%' . $wpdb->esc_like($permalink) . '%'
                ));
                
                if (!$has_link) {
                    $orphan_meta_count++;
                }
            }
            // Extrapolate from sample
            if ($sample_size > 0) {
                $orphan_meta_count = intval(($orphan_meta_count / $sample_size) * count($all_posts));
            }
        } else {
            $orphan_meta_count = count($all_posts) - count($linked_posts);
        }
    }
    
    // Get REAL internal links count by parsing content
    $site_url = get_site_url();
    $internal_links = 0;
    $external_links = 0;
    $posts_with_links = 0;
    $total_anchor_length = 0;
    $anchor_count = 0;
    
    // Analyze sample of posts for efficiency
    $sample_posts = array_slice($all_posts, 0, 20); // Sample first 20 posts
    foreach ($sample_posts as $post) {
        $content = get_post_field('post_content', $post['ID']);
        if (!empty($content) && preg_match_all('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>([^<]*)<\/a>/i', $content, $matches)) {
            $posts_with_links++;
            foreach ($matches[1] as $index => $url) {
                if (strpos($url, $site_url) !== false || strpos($url, '/') === 0) {
                    $internal_links++;
                } else if (strpos($url, 'http') === 0) {
                    $external_links++;
                }
                // Track anchor text length
                $anchor_text = wp_strip_all_tags($matches[2][$index] ?? '');
                if (!empty($anchor_text)) {
                    $total_anchor_length += strlen($anchor_text);
                    $anchor_count++;
                }
            }
        }
    }
    
    // Extrapolate to full dataset
    if (count($sample_posts) > 0) {
        $multiplier = $total_posts / count($sample_posts);
        $internal_links = intval($internal_links * $multiplier);
        $external_links = intval($external_links * $multiplier);
        $posts_with_links = intval($posts_with_links * $multiplier);
    }
    
    // Calculate REAL metrics from actual data
    $link_coverage = $total_posts > 0 ? round(($posts_with_links / $total_posts) * 100, 2) : 0;
    
    // Get click count if table exists
    $click_count = 0;
    $clicks_table = $wpdb->prefix . 'prorank_link_clicks';
    if ($wpdb->get_var("SHOW TABLES LIKE '$clicks_table'") === $clicks_table) {
        $click_count = $wpdb->get_var("SELECT COUNT(*) FROM $clicks_table") ?: 0;
    }
    
    // Calculate REAL quality scores based on actual data
    // Link quality score based on coverage and distribution
    $link_quality_score = 0;
    if ($link_coverage > 0) {
        $link_quality_score += min(50, $link_coverage / 2); // 50% weight for coverage
    }
    if ($internal_links > 0 && $total_posts > 0) {
        $avg_links = $internal_links / $total_posts;
        // Ideal is 3-5 links per post
        if ($avg_links >= 3 && $avg_links <= 5) {
            $link_quality_score += 50;
        } else if ($avg_links >= 2 && $avg_links <= 7) {
            $link_quality_score += 35;
        } else if ($avg_links >= 1) {
            $link_quality_score += 20;
        }
    }
    $link_quality_score = min(100, max(0, intval($link_quality_score)));
    
    // Calculate REAL anchor text quality score
    $anchor_length_score = 0;
    if ($anchor_count > 0) {
        $avg_anchor_length = $total_anchor_length / $anchor_count;
        // Ideal anchor text is 3-6 words (15-30 characters)
        if ($avg_anchor_length >= 15 && $avg_anchor_length <= 30) {
            $anchor_length_score = 90;
        } else if ($avg_anchor_length >= 10 && $avg_anchor_length <= 40) {
            $anchor_length_score = 70;
        } else if ($avg_anchor_length >= 5 && $avg_anchor_length <= 50) {
            $anchor_length_score = 50;
        } else {
            $anchor_length_score = 30;
        }
    }
    
    // Calculate REAL internal/external ratio
    $total_links = $internal_links + $external_links;
    $external_ratio = $total_links > 0 ? round(($internal_links / $total_links) * 100, 0) : 0;
    
    // Get most linked domains efficiently using sample
    $most_linked_domains = [];
    $domain_counts = [];
    
    // Sample content for domain analysis
    foreach ($sample_posts as $post) {
        $content = get_post_field('post_content', $post['ID']);
        if (!empty($content) && preg_match_all('/<a[^>]+href=["\']https?:\/\/([^"\'\/]+)/i', $content, $matches)) {
            foreach ($matches[1] as $domain) {
                if (!isset($domain_counts[$domain])) {
                    $domain_counts[$domain] = 0;
                }
                $domain_counts[$domain]++;
            }
        }
    }
    
    // Sort by count and get top 3
    if (!empty($domain_counts)) {
        arsort($domain_counts);
        $top_domains = array_slice($domain_counts, 0, 3, true);
        
        foreach ($top_domains as $domain => $count) {
            $most_linked_domains[] = [
                'domain' => $domain,
                'count' => $count
            ];
        }
    }
    
    // Quick broken links check on sample
    $broken_links = 0;
    $broken_links_list = [];
    
    // Check only first 5 posts for broken links to avoid timeout
    $check_posts = array_slice($sample_posts, 0, 5);
    foreach ($check_posts as $post) {
        $content = get_post_field('post_content', $post['ID']);
        if (!empty($content) && preg_match_all('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) {
            foreach ($matches[1] as $url) {
                // Check internal links only
                if (strpos($url, $site_url) !== false || strpos($url, '/') === 0) {
                    $full_url = (strpos($url, '/') === 0) ? $site_url . $url : $url;
                    $target_id = url_to_postid($full_url);
                    
                    // If no post found for this URL, it might be broken
                    if ($target_id === 0 && strpos($full_url, $site_url) !== false) {
                        $broken_links++;
                        if (count($broken_links_list) < 3) {
                            $broken_links_list[] = [
                                'source' => $post['post_title'],
                                'url' => $full_url
                            ];
                        }
                    }
                }
            }
        }
    }
    
    // Build response
    $data = [
        'posts_crawled' => $total_posts,
        'link_clicks' => $click_count,
        'orphaned_posts' => $orphan_meta_count,
        'broken_links' => $broken_links,
        'link_coverage' => $link_coverage,
        'link_quality_score' => $link_quality_score,
        'external_site_focus' => $external_ratio,
        'anchor_length_score' => $anchor_length_score,
        'total_internal_links' => $internal_links,
        'average_links_per_post' => $total_posts > 0 ? round($internal_links / $total_posts, 1) : 0,
        'posts_without_links' => $orphan_meta_count,
        'most_linked_domains' => $most_linked_domains,
        'recent_broken_links' => $broken_links_list,
        'ai_enabled' => class_exists('\ProRank\SEO\AI\Manager'),
        'gsc_connected' => !empty(get_option('prorank_seo_gsc_property', '')),
    ];
    
    return rest_ensure_response([
        'success' => true,
        'data' => $data,
    ]);
}

/**
 * Run link scan analysis
 */
function run_link_scan(WP_REST_Request $request): WP_REST_Response {
    global $wpdb;
    
    $scan_type = $request->get_param('scan_type');
    
    // Start scan
    set_transient('prorank_link_scan_status', 'running', 300);
    
    // Get all posts
    $posts = get_posts([
        'post_type' => ['post', 'page'],
        'post_status' => 'publish',
        'numberposts' => -1,
    ]);
    
    $total_posts = count($posts);
    $orphaned_posts = [];
    $broken_links = [];
    $link_opportunities = [];
    
    // Analyze each post
    foreach ($posts as $index => $post) {
        // Update progress
        $progress = intval(($index / $total_posts) * 100);
        set_transient('prorank_link_scan_progress', $progress, 300);
        
        $content = $post->post_content;
        $permalink = get_permalink($post->ID);
        
        // Check for orphaned posts (no incoming links)
        $has_incoming = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->posts} 
            WHERE post_status = 'publish' 
            AND ID != %d 
            AND post_content LIKE %s",
            $post->ID,
            '%' . $permalink . '%'
        )) > 0;
        
        if (!$has_incoming) {
            $orphaned_posts[] = [
                'id' => $post->ID,
                'title' => $post->post_title,
                'url' => $permalink,
            ];
        }
        
        // Check for broken internal links
        if (preg_match_all('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) {
            foreach ($matches[1] as $url) {
                if (strpos($url, get_site_url()) !== false || strpos($url, '/') === 0) {
                    $target_id = url_to_postid($url);
                    if ($target_id === 0) {
                        $broken_links[] = [
                            'source' => $post->post_title,
                            'source_id' => $post->ID,
                            'url' => $url,
                        ];
                    }
                }
            }
        }
        
        // Find link opportunities (posts without enough internal links)
        $link_count = substr_count($content, 'href=');
        if ($link_count < 2) {
            $link_opportunities[] = [
                'id' => $post->ID,
                'title' => $post->post_title,
                'current_links' => $link_count,
                'suggested_links' => 3,
            ];
        }
    }
    
    // Save scan results
    $scan_results = [
        'last_scan' => current_time('mysql'),
        'total_posts' => $total_posts,
        'orphaned_posts' => $orphaned_posts,
        'broken_links' => array_slice($broken_links, 0, 50), // Limit to 50
        'link_opportunities' => array_slice($link_opportunities, 0, 50), // Limit to 50
        'link_stats' => [
            'total_internal_links' => $wpdb->get_var(
                "SELECT COUNT(*) FROM {$wpdb->posts} 
                WHERE post_status = 'publish' 
                AND post_content LIKE '%href=%'"
            ) ?: 0,
            'average_links_per_post' => $total_posts > 0 ? round(count($broken_links) / $total_posts, 1) : 0,
            'posts_without_links' => count($link_opportunities),
            'posts_with_too_many_links' => 0,
        ],
    ];
    
    // Store results
    update_option('prorank_link_scan_results', $scan_results);
    set_transient('prorank_link_scan_status', 'completed', 300);
    
    return rest_ensure_response([
        'success' => true,
        'data' => $scan_results,
    ]);
}
