<?php
declare(strict_types=1);
// ==================================================
// Nuclear Fancy Pants Edition™ -- NUCLEAR+++
// File: /home/ploi/automarketer-ai.com/public/wp-content/plugins/automarketer-ai/includes/class-sentiment-scorer.php
// Description: Scores comments in wp_amai_social_comments as positive, neutral, or negative using the active AI provider - NUCLEAR+++
// Last Edited: 2026-05-20
// ==================================================
namespace AutoMarketerAI;
defined('ABSPATH') || exit;

class SentimentScorer
{
    private const CRON_HOOK = 'amai_score_comment';

    // Score map: word returned by AI -> enum value + numeric score
    private const SCORE_MAP = [
        'positive' => ['sentiment' => 'positive', 'score' => 80],
        'neutral'  => ['sentiment' => 'neutral',  'score' => 0],
        'negative' => ['sentiment' => 'negative', 'score' => -80],
    ];

    // --------------------------------------------------
    // Register the cron action hook unconditionally.
    // Scheduled as a single event from CommentFetcher
    // after each new comment insert.
    // --------------------------------------------------
    public static function register(): void
    {
        add_action(self::CRON_HOOK, [self::class, 'score']);
    }

    // --------------------------------------------------
    // Score a single comment by ID.
    // Loads content, calls AI, writes result back.
    // Silent no-op on any failure -- never blocks the caller.
    // --------------------------------------------------
    public static function score(int $comment_id): void
    {
        if ($comment_id <= 0) {
            return;
        }

        global $wpdb;
        $table = $wpdb->prefix . 'amai_social_comments';

        $row = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT id, content, sentiment FROM `{$table}` WHERE id = %d LIMIT 1",
                $comment_id
            ),
            ARRAY_A
        );

        if (!is_array($row) || (string) ($row['content'] ?? '') === '') {
            return;
        }

        // Skip if already scored.
        if (($row['sentiment'] ?? 'unscored') !== 'unscored') {
            return;
        }

        $result = self::callAi((string) $row['content']);
        if ($result === null) {
            return;
        }

        $wpdb->query(
            $wpdb->prepare(
                "UPDATE `{$table}` SET sentiment = %s, sentiment_score = %d WHERE id = %d",
                $result['sentiment'],
                $result['score'],
                $comment_id
            )
        );
    }

    // --------------------------------------------------
    // Query sentiment breakdown for a given time window.
    // Returns ['positive' => int, 'neutral' => int, 'negative' => int, 'total' => int].
    // --------------------------------------------------
    public static function getSummary(int $days = 30): array
    {
        global $wpdb;
        $table = $wpdb->prefix . 'amai_social_comments';

        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT sentiment, COUNT(*) AS cnt
                   FROM `{$table}`
                  WHERE sentiment != 'unscored'
                    AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d DAY)
                  GROUP BY sentiment",
                $days
            ),
            ARRAY_A
        );

        $out = ['positive' => 0, 'neutral' => 0, 'negative' => 0, 'total' => 0];
        if (!is_array($rows)) {
            return $out;
        }
        foreach ($rows as $r) {
            $key = (string) ($r['sentiment'] ?? '');
            if (isset($out[$key])) {
                $out[$key] = (int) $r['cnt'];
            }
        }
        $out['total'] = $out['positive'] + $out['neutral'] + $out['negative'];
        return $out;
    }

    // --------------------------------------------------
    // Call AI provider to classify sentiment.
    // Returns ['sentiment' => string, 'score' => int] or null on failure.
    // Uses Claude via KeyVault -- same pattern as CommentResponder.
    // --------------------------------------------------
    private static function callAi(string $content): ?array
    {
        $api_key_enc = (string) get_option('amai_api_key_ai-claude', '');
        if ($api_key_enc === '') {
            return null;
        }

        $api_key = KeyVault::decrypt($api_key_enc);
        if ($api_key === '' || $api_key === false) {
            return null;
        }

        $module_path = AMAI_PLUGIN_DIR . 'modules/ai-claude.php';
        if (!is_file($module_path)) {
            return null;
        }
        require_once $module_path;

        if (!class_exists('AutoMarketerAI\\Modules\\Claude')) {
            return null;
        }

        $module = new \AutoMarketerAI\Modules\Claude();
        $model  = $module->get_default_model();

        $content_trimmed = mb_substr(trim($content), 0, 280);
        $prompt = 'Classify the sentiment of this comment as exactly one word: positive, neutral, or negative. Reply with only that one word, nothing else.' . "\n\n" . $content_trimmed;

        try {
            $raw = trim(strtolower($module->generate_raw($prompt, (string) $api_key, $model, 10)));
        } catch (\Throwable $e) {
            return null;
        }

        // Strip any punctuation the model might have added.
        $raw = preg_replace('/[^a-z]/', '', $raw);

        return self::SCORE_MAP[$raw] ?? null;
    }
}