<?php

namespace App\Services\Posts;

use App\Models\Post;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * Tracks post impressions (throttled per session) and computes engagement score.
 *
 * Impression throttle: 1 impression per post per session-key per hour.
 * Engagement score: (reactions*2 + comments*3 + saves) / max(impressions, 1)
 */
class PostAnalyticsService
{
    /**
     * Record a post impression, throttled by a session key.
     * Returns true if impression was counted, false if throttled.
     */
    public function trackImpression(Post $post, string $sessionKey): bool
    {
        $cacheKey = "impression:{$post->id}:{$sessionKey}";

        if (Cache::has($cacheKey)) {
            return false; // already counted this hour
        }

        Cache::put($cacheKey, 1, now()->addHour());

        Post::withoutTimestamps(function () use ($post) {
            DB::table('posts')
                ->where('id', $post->id)
                ->increment('impressions_count');
        });

        // Recompute engagement score asynchronously via a quick DB update
        $this->refreshEngagementScore($post->id);

        return true;
    }

    /**
     * Refresh the cached engagement_score = (reactions*2 + comments*3 + saves) / max(impressions, 1)
     */
    public function refreshEngagementScore(int $postId): void
    {
        Post::withoutTimestamps(function () use ($postId) {
            DB::table('posts')
                ->where('id', $postId)
                ->update([
                    'engagement_score' => DB::raw(
                        '(reactions_count * 2 + comments_count * 3 + saves_count) / GREATEST(impressions_count, 1)'
                    ),
                ]);
        });
    }

    /**
     * Return analytics summary for a post (owner view).
     */
    public function getSummary(Post $post): array
    {
        $reactions  = $post->reactions_count;
        $comments   = $post->comments_count;
        $saves      = $post->saves_count;
        $impressions = $post->impressions_count;
        $rate       = $impressions > 0
            ? round((($reactions + $comments + $saves) / $impressions) * 100, 2)
            : 0.0;

        return [
            'impressions'      => $impressions,
            'reactions'        => $reactions,
            'comments'         => $comments,
            'saves'            => $saves,
            'engagement_rate'  => $rate, // percentage
            'engagement_score' => round($post->engagement_score, 4),
        ];
    }
}
