<?php

declare(strict_types=1);

namespace ProRank\SEO\Core\Content;

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

/**
 * Scans content for AI chat surface metadata leaks across vendors
 * (ChatGPT, Claude, Gemini, Copilot, Perplexity, Draft.js editors).
 *
 * The presence of these attributes is direct evidence of unfiltered AI paste,
 * a "scaled content abuse" risk under Google's spam policy. Detection is
 * non-destructive — the AiAttributeStripper handles cleanup separately.
 */
class AiContentLeakAuditor {

    public function scan(): array {
        global $wpdb;

        $attributes = AiContentLeakSignatures::all_attributes();

        $like_clauses = [];
        $params = [];
        foreach ($attributes as $attr) {
            $like_clauses[] = '(post_content LIKE %s OR post_excerpt LIKE %s)';
            $like = '%' . $wpdb->esc_like($attr) . '%';
            $params[] = $like;
            $params[] = $like;
        }
        $where = implode(' OR ', $like_clauses);

        $sql = $wpdb->prepare(
            "SELECT ID, post_title, post_type, post_status, post_date, post_modified, post_content, post_excerpt
             FROM {$wpdb->posts}
             WHERE post_status IN ('publish','future','draft','pending','private')
               AND ({$where})",
            $params
        );

        $rows = $wpdb->get_results($sql, ARRAY_A) ?: [];

        $offenders = [];
        $totals = [
            'high_confidence' => 0,
            'ambiguous' => 0,
        ];
        $by_vendor = [];
        $by_post_type = [];

        foreach ($rows as $row) {
            $content_breakdown = $this->breakdown((string) $row['post_content']);
            $excerpt_breakdown = $this->breakdown((string) ($row['post_excerpt'] ?? ''));

            $combined = $this->merge_breakdowns($content_breakdown, $excerpt_breakdown);
            if ($combined['total'] <= 0) {
                continue;
            }

            $offenders[] = [
                'id' => (int) $row['ID'],
                'title' => (string) $row['post_title'],
                'type' => (string) $row['post_type'],
                'status' => (string) $row['post_status'],
                'date' => (string) $row['post_date'],
                'modified' => (string) $row['post_modified'],
                'content_leaks' => $content_breakdown['total'],
                'excerpt_leaks' => $excerpt_breakdown['total'],
                'high_confidence' => $combined['high_confidence'],
                'ambiguous' => $combined['ambiguous'],
                'by_vendor' => $combined['by_vendor'],
                'by_attribute' => $combined['by_attribute'],
                'edit_link' => admin_url('post.php?post=' . (int) $row['ID'] . '&action=edit'),
                'permalink' => (string) get_permalink((int) $row['ID']),
            ];

            $totals['high_confidence'] += $combined['high_confidence'];
            $totals['ambiguous'] += $combined['ambiguous'];

            foreach ($combined['by_vendor'] as $vendor => $count) {
                $by_vendor[$vendor] = ($by_vendor[$vendor] ?? 0) + $count;
            }
            $by_post_type[$row['post_type']] = ($by_post_type[$row['post_type']] ?? 0) + 1;
        }

        usort($offenders, static function ($a, $b) {
            $a_total = $a['high_confidence'] + $a['ambiguous'];
            $b_total = $b['high_confidence'] + $b['ambiguous'];
            return $b_total <=> $a_total;
        });

        $elementor = $this->scan_elementor_postmeta();
        $terms = $this->scan_term_descriptions();

        return [
            'scanned_at' => current_time('mysql'),
            'offender_count' => count($offenders),
            'totals' => $totals,
            'by_vendor' => $by_vendor,
            'by_post_type' => $by_post_type,
            'offenders' => $offenders,
            'elementor' => $elementor,
            'terms' => $terms,
        ];
    }

    private function scan_term_descriptions(): array {
        global $wpdb;

        $attributes = AiContentLeakSignatures::all_attributes();

        $like_clauses = [];
        $params = [];
        foreach ($attributes as $attr) {
            $like_clauses[] = 'tt.description LIKE %s';
            $params[] = '%' . $wpdb->esc_like($attr . '=') . '%';
        }
        $where = implode(' OR ', $like_clauses);

        $sql = $wpdb->prepare(
            "SELECT tt.term_taxonomy_id, tt.term_id, tt.taxonomy, tt.description, t.name
             FROM {$wpdb->term_taxonomy} tt
             INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
             WHERE {$where}",
            $params
        );

        $rows = $wpdb->get_results($sql, ARRAY_A) ?: [];

        $hits = [];
        $totals = [
            'high_confidence' => 0,
            'ambiguous' => 0,
        ];

        foreach ($rows as $row) {
            $breakdown = $this->breakdown((string) $row['description']);
            if ($breakdown['total'] <= 0) {
                continue;
            }

            $hits[] = [
                'term_id' => (int) $row['term_id'],
                'term_taxonomy_id' => (int) $row['term_taxonomy_id'],
                'taxonomy' => (string) $row['taxonomy'],
                'name' => (string) $row['name'],
                'high_confidence' => $breakdown['high_confidence'],
                'ambiguous' => $breakdown['ambiguous'],
                'by_vendor' => $breakdown['by_vendor'],
                'edit_link' => admin_url('term.php?taxonomy=' . urlencode((string) $row['taxonomy']) . '&tag_ID=' . (int) $row['term_id']),
            ];

            $totals['high_confidence'] += $breakdown['high_confidence'];
            $totals['ambiguous'] += $breakdown['ambiguous'];
        }

        usort($hits, static function ($a, $b) {
            return ($b['high_confidence'] + $b['ambiguous']) <=> ($a['high_confidence'] + $a['ambiguous']);
        });

        return [
            'item_count' => count($hits),
            'totals' => $totals,
            'items' => $hits,
        ];
    }

    private function scan_elementor_postmeta(): array {
        global $wpdb;

        $attributes = AiContentLeakSignatures::all_attributes();

        $like_clauses = [];
        $params = [];
        foreach ($attributes as $attr) {
            $like_clauses[] = 'pm.meta_value LIKE %s';
            $params[] = '%' . $wpdb->esc_like($attr) . '%';
        }
        $where = implode(' OR ', $like_clauses);

        $sql = $wpdb->prepare(
            "SELECT pm.post_id AS id, p.post_title AS title, p.post_type AS type, p.post_status AS status, pm.meta_value AS data
             FROM {$wpdb->postmeta} pm
             INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
             WHERE pm.meta_key = '_elementor_data'
               AND p.post_status IN ('publish','future','draft','pending','private')
               AND ({$where})",
            $params
        );

        $rows = $wpdb->get_results($sql, ARRAY_A) ?: [];

        $hits = [];
        $totals = [
            'high_confidence' => 0,
            'ambiguous' => 0,
        ];

        foreach ($rows as $row) {
            $breakdown = $this->breakdown_json((string) $row['data']);
            if ($breakdown['total'] <= 0) {
                continue;
            }

            $hits[] = [
                'id' => (int) $row['id'],
                'title' => (string) $row['title'],
                'type' => (string) $row['type'],
                'status' => (string) $row['status'],
                'high_confidence' => $breakdown['high_confidence'],
                'ambiguous' => $breakdown['ambiguous'],
                'by_vendor' => $breakdown['by_vendor'],
                'edit_link' => admin_url('post.php?post=' . (int) $row['id'] . '&action=elementor'),
            ];

            $totals['high_confidence'] += $breakdown['high_confidence'];
            $totals['ambiguous'] += $breakdown['ambiguous'];
        }

        usort($hits, static function ($a, $b) {
            return ($b['high_confidence'] + $b['ambiguous']) <=> ($a['high_confidence'] + $a['ambiguous']);
        });

        return [
            'item_count' => count($hits),
            'totals' => $totals,
            'items' => $hits,
        ];
    }

    public function breakdown(string $html): array {
        $by_attribute = [];
        $by_vendor = [];
        $high = 0;
        $ambig = 0;

        foreach (AiContentLeakSignatures::HIGH_CONFIDENCE as $attr => $vendor) {
            $n = $this->count_attribute_assignments($html, $attr);
            if ($n > 0) {
                $by_attribute[$attr] = $n;
                $by_vendor[$vendor] = ($by_vendor[$vendor] ?? 0) + $n;
                $high += $n;
            }
        }
        foreach (AiContentLeakSignatures::AMBIGUOUS as $attr => $vendor) {
            $n = $this->count_attribute_assignments($html, $attr);
            if ($n > 0) {
                $by_attribute[$attr] = $n;
                $by_vendor[$vendor] = ($by_vendor[$vendor] ?? 0) + $n;
                $ambig += $n;
            }
        }

        return [
            'total' => $high + $ambig,
            'high_confidence' => $high,
            'ambiguous' => $ambig,
            'by_attribute' => $by_attribute,
            'by_vendor' => $by_vendor,
        ];
    }

    public function breakdown_json(string $json): array {
        $by_attribute = [];
        $by_vendor = [];
        $high = 0;
        $ambig = 0;

        foreach (AiContentLeakSignatures::HIGH_CONFIDENCE as $attr => $vendor) {
            $n = $this->count_attribute_assignments($json, $attr);
            if ($n > 0) {
                $by_attribute[$attr] = $n;
                $by_vendor[$vendor] = ($by_vendor[$vendor] ?? 0) + $n;
                $high += $n;
            }
        }
        foreach (AiContentLeakSignatures::AMBIGUOUS as $attr => $vendor) {
            $n = $this->count_attribute_assignments($json, $attr);
            if ($n > 0) {
                $by_attribute[$attr] = $n;
                $by_vendor[$vendor] = ($by_vendor[$vendor] ?? 0) + $n;
                $ambig += $n;
            }
        }

        return [
            'total' => $high + $ambig,
            'high_confidence' => $high,
            'ambiguous' => $ambig,
            'by_attribute' => $by_attribute,
            'by_vendor' => $by_vendor,
        ];
    }

    private function count_attribute_assignments(string $text, string $attribute): int {
        $pattern = '/(?<![A-Za-z0-9_-])' . preg_quote($attribute, '/') . '\s*=/i';
        return (int) preg_match_all($pattern, $text);
    }

    private function merge_breakdowns(array $a, array $b): array {
        $by_attribute = $a['by_attribute'];
        foreach ($b['by_attribute'] as $attr => $count) {
            $by_attribute[$attr] = ($by_attribute[$attr] ?? 0) + $count;
        }
        $by_vendor = $a['by_vendor'];
        foreach ($b['by_vendor'] as $vendor => $count) {
            $by_vendor[$vendor] = ($by_vendor[$vendor] ?? 0) + $count;
        }
        return [
            'total' => $a['total'] + $b['total'],
            'high_confidence' => $a['high_confidence'] + $b['high_confidence'],
            'ambiguous' => $a['ambiguous'] + $b['ambiguous'],
            'by_attribute' => $by_attribute,
            'by_vendor' => $by_vendor,
        ];
    }
}
