<?php
declare(strict_types=1);
// ==================================================
// Nuclear Fancy Pants Edition™ — NUCLEAR+++
// File: /includes/class-performance-analyzer.php
// Description: Analyzes real post engagement stats to produce per-channel performance insights for content generation - NUCLEAR+++
// Last Edited: 2026-04-22
// ==================================================

namespace AutoMarketerAI;

defined('ABSPATH') || exit;

final class PerformanceAnalyzer
{
    // Minimum number of posts with real stat data before we trust the signal
    private const MIN_SIGNAL_POSTS = 8;

    // Rolling window in days - older data ages out naturally
    private const WINDOW_DAYS = 60;

    // Engagement score weights
    private const WEIGHT_LIKES    = 1;
    private const WEIGHT_COMMENTS = 3;   // comments signal real intent - weighted heavily
    private const WEIGHT_REACH    = 0.01; // reach is passive - low weight

    // ---------------------------------------------------------------------------
    // Public API
    // ---------------------------------------------------------------------------

    // Returns performance insights for a given channel, or null if not enough data.
    // Shape:
    // [
    //   'has_signal'    => true,
    //   'total_posts'   => 23,
    //   'top_types'     => ['educational', 'humor'],
    //   'weak_types'    => ['product'],
    //   'avg_by_type'   => ['educational' => 47.2, 'humor' => 38.1, ...],
    //   'summary'       => 'educational and humor posts drive the most engagement...',
    // ]
    public static function analyze(string $channel): ?array
    {
        global $wpdb;

        $table  = $wpdb->prefix . 'amai_scheduled_posts';
        $cutoff = gmdate('Y-m-d H:i:s', strtotime('-' . self::WINDOW_DAYS . ' days'));

        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT `post_type`, `stat_likes`, `stat_comments`, `stat_reach`" .
                " FROM `{$table}`" .
                " WHERE `channel` = %s" .
                "   AND `status` = 'posted'" .
                "   AND `stats_fetched_at` IS NOT NULL" .
                "   AND `created_at` >= %s" .
                "   AND `post_type` IS NOT NULL" .
                "   AND `post_type` <> ''",
                $channel,
                $cutoff
            ),
            ARRAY_A
        );

        if (empty($rows) || count($rows) < self::MIN_SIGNAL_POSTS) {
            return null;
        }

        // Compute per-type engagement scores
        $type_scores = [];
        $type_counts = [];

        foreach ($rows as $row) {
            $type     = (string) $row['post_type'];
            $likes    = (int) ($row['stat_likes']    ?? 0);
            $comments = (int) ($row['stat_comments'] ?? 0);
            $reach    = (int) ($row['stat_reach']    ?? 0);

            $score = ($likes * self::WEIGHT_LIKES)
                   + ($comments * self::WEIGHT_COMMENTS)
                   + ($reach * self::WEIGHT_REACH);

            if (!isset($type_scores[$type])) {
                $type_scores[$type] = 0.0;
                $type_counts[$type] = 0;
            }

            $type_scores[$type] += $score;
            $type_counts[$type]++;
        }

        // Average score per type
        $avg_by_type = [];
        foreach ($type_scores as $type => $total) {
            $avg_by_type[$type] = round($total / $type_counts[$type], 2);
        }

        arsort($avg_by_type);

        $sorted_types = array_keys($avg_by_type);
        $count        = count($sorted_types);

        // Top types: upper third, minimum 1
        $top_count  = max(1, (int) ceil($count / 3));
        $weak_count = max(1, (int) ceil($count / 3));

        $top_types  = array_slice($sorted_types, 0, $top_count);
        $weak_types = array_slice($sorted_types, $count - $weak_count);

        // Only flag weak types if they genuinely underperform - score below half the top average
        $top_avg    = count($top_types) > 0 ? ($avg_by_type[$top_types[0]] ?? 0.0) : 0.0;
        $weak_types = array_values(array_filter($weak_types, function (string $t) use ($avg_by_type, $top_avg): bool {
            return $top_avg > 0 && ($avg_by_type[$t] ?? 0.0) < ($top_avg * 0.5);
        }));

        return [
            'has_signal'  => true,
            'total_posts' => count($rows),
            'top_types'   => $top_types,
            'weak_types'  => $weak_types,
            'avg_by_type' => $avg_by_type,
        ];
    }

    // Returns insights for all active channels in one call.
    // ContentEngine calls this once per generation run.
    public static function analyzeAll(): array
    {
        $channels = ['facebook', 'instagram', 'tiktok', 'x', 'google'];
        $result   = [];

        foreach ($channels as $channel) {
            $insights = self::analyze($channel);
            if ($insights !== null) {
                $result[$channel] = $insights;
            }
        }

        return $result;
    }

    // Formats insights into a prompt-ready string for injection into AI prompts.
    // Returns empty string if no signal.
    public static function formatForPrompt(array $insights): string
    {
        if (empty($insights) || !($insights['has_signal'] ?? false)) {
            return '';
        }

        $top  = $insights['top_types']  ?? [];
        $weak = $insights['weak_types'] ?? [];

        if (empty($top)) {
            return '';
        }

        $lines   = [];
        $lines[] = 'Audience performance data (based on this account\'s real post history):';
        $lines[] = '- Posts that drive the most engagement for this audience: ' . implode(', ', $top);

        if (!empty($weak)) {
            $lines[] = '- Posts that underperform for this audience: ' . implode(', ', $weak);
            $lines[] = '- For underperforming types, try a noticeably different angle than usual - same post type, fresh approach.';
        }

        $lines[] = '- Lean into what resonates. The data above reflects this specific audience, not a general rule.';
        $lines[] = '- Never skip a required post type. Adjust tone and angle, not the type itself.';

        return implode("\n", $lines);
    }
}