<?php

namespace App\Support;

use App\Models\Lead;
use App\Models\Withdrawal;
use Illuminate\Support\Collection;

final class CommunityActivityFeed
{
    /**
     * Build the shared public/user activity rail with one aggregate query.
     * Private members expose only identity and lifetime earning totals.
     */
    public static function recent(int $limit = 12): Collection
    {
        $leads = Lead::query()
            ->with('user')
            ->where('credited_points', '>', 0)
            ->whereHas('user')
            ->latest('updated_at')
            ->take(24)
            ->get();

        $withdrawals = Withdrawal::query()
            ->with('user')
            ->where('status', 'approved')
            ->where('amount', '>', 0)
            ->whereHas('user')
            ->latest('updated_at')
            ->take(24)
            ->get();

        $events = $leads->map(fn (Lead $lead): array => [
            'kind' => 'earning', 'model' => $lead, 'user_id' => $lead->user_id, 'at' => $lead->updated_at,
        ])->concat($withdrawals->map(fn (Withdrawal $withdrawal): array => [
            'kind' => 'withdrawal', 'model' => $withdrawal, 'user_id' => $withdrawal->user_id, 'at' => $withdrawal->updated_at,
        ]))->sortByDesc('at')->take(max(1, min($limit, 24)))->values();

        if ($events->isEmpty()) {
            return collect();
        }

        $userIds = $events->pluck('user_id')->unique()->values();
        $totals = Lead::query()
            ->selectRaw('user_id, COUNT(*) as completed_offers, COALESCE(SUM(credited_points), 0) as total_points')
            ->where('credited_points', '>', 0)
            ->whereIn('user_id', $userIds)
            ->groupBy('user_id')
            ->get()
            ->keyBy('user_id');
        $recentByUser = $events->groupBy('user_id');

        return $events->map(function (array $event) use ($totals, $recentByUser): array {
            $activity = $event['model'];
            $isWithdrawal = $event['kind'] === 'withdrawal';
            $user = $activity->user;
            $summary = $totals->get($user->id);
            $isPrivate = (bool) $user->is_profile_private;
            $recent = $isPrivate ? [] : $recentByUser->get($user->id, collect())
                ->take(5)
                ->map(function (array $item): array {
                    $model = $item['model'];
                    $withdrawal = $item['kind'] === 'withdrawal';

                    return [
                        'offer' => $withdrawal ? 'Withdrawal paid' : html_entity_decode($model->offer_name ?: 'Offer completed'),
                        'type' => $item['kind'],
                        'provider' => $withdrawal ? ($model->method ?: 'Reward payout') : ($model->company ?: 'Basketloot'),
                        'coins' => number_format((float) ($withdrawal ? $model->amount : $model->credited_points)),
                        'usd' => format_coins_as_usd($withdrawal ? $model->amount : $model->credited_points),
                        'time' => $model->updated_at?->diffForHumans() ?? 'Recently',
                    ];
                })->values()->all();

            $latestPoints = (float) ($isWithdrawal ? $activity->amount : $activity->credited_points);

            return [
                'lead' => $activity,
                'activity_type' => $event['kind'],
                'user' => $user,
                'username' => $user->username,
                'avatar' => $user->avatar(),
                'is_private' => $isPrivate,
                'joined' => $user->created_at?->format('M Y') ?? 'Member',
                'completed_offers' => (int) ($summary->completed_offers ?? 0),
                'total_points' => (float) ($summary->total_points ?? 0),
                'total_usd' => format_coins_as_usd($summary->total_points ?? 0),
                'latest_offer' => $isPrivate ? null : ($isWithdrawal ? 'Withdrawal paid' : html_entity_decode($activity->offer_name ?: 'Offer completed')),
                'latest_provider' => $isPrivate ? null : ($isWithdrawal ? ($activity->method ?: 'Reward payout') : ($activity->company ?: 'Basketloot')),
                'latest_coins' => $isPrivate ? null : number_format($latestPoints),
                'latest_usd' => $isPrivate ? null : format_coins_as_usd($latestPoints),
                'latest_payout' => $isPrivate ? null : number_format((float) ($isWithdrawal ? coins_to_usd($activity->amount) : $activity->payout), 2),
                'latest_time' => $activity->updated_at?->diffForHumans() ?? 'Recently',
                'recent' => $recent,
            ];
        });
    }
}
