<?php

namespace App\Services\Posts;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Collection as BaseCollection;

/**
 * Aggregates database notification records into digest groups
 * so the UI shows "12 people liked your post" instead of 12 separate entries.
 *
 * Grouping key: (notifiable_id, data->type, data->post_id, 1-hour bucket)
 */
class NotificationDigestService
{
    /**
     * Aggregate a raw notification collection into digest entries.
     *
     * @param  \Illuminate\Database\Eloquent\Collection $notifications
     * @return array<array{
     *   type: string,
     *   count: int,
     *   actors: array,
     *   post_id: int|null,
     *   message: string,
     *   url: string|null,
     *   latest_at: string,
     *   read: bool,
     *   ids: int[],
     * }>
     */
    public function aggregate(Collection $notifications): array
    {
        $groups = [];

        foreach ($notifications as $notif) {
            $data     = is_array($notif->data) ? $notif->data : json_decode($notif->data, true);
            $type     = $data['type']    ?? 'unknown';
            $postId   = $data['post_id'] ?? null;

            // 1-hour bucket
            $bucket = $notif->created_at->format('Y-m-d H');

            $key = "{$type}:{$postId}:{$bucket}";

            if (! isset($groups[$key])) {
                $groups[$key] = [
                    'type'      => $type,
                    'count'     => 0,
                    'actors'    => [],
                    'post_id'   => $postId,
                    'url'       => $data['url'] ?? null,
                    'latest_at' => $notif->created_at->toISOString(),
                    'read'      => $notif->read_at !== null,
                    'ids'       => [],
                ];
            }

            $groups[$key]['count']++;
            $groups[$key]['ids'][] = $notif->id;

            // Collect unique actors (up to 5 for display)
            $actorId = $data['commenter_id'] ?? $data['reactor_id'] ?? $data['actor_id'] ?? null;
            if ($actorId && count($groups[$key]['actors']) < 5) {
                $alreadyAdded = collect($groups[$key]['actors'])->contains('id', $actorId);
                if (! $alreadyAdded) {
                    $groups[$key]['actors'][] = [
                        'id'       => $actorId,
                        'name'     => $data['commenter_name'] ?? $data['actor_name'] ?? null,
                        'username' => $data['commenter_username'] ?? $data['actor_username'] ?? null,
                    ];
                }
            }

            if ($notif->read_at === null) {
                $groups[$key]['read'] = false; // group is unread if any item is unread
            }
        }

        // Build readable message for each group
        $result = [];
        foreach ($groups as $group) {
            $group['message'] = $this->buildMessage($group);
            $result[]         = $group;
        }

        // Sort by latest_at descending
        usort($result, fn ($a, $b) => strcmp($b['latest_at'], $a['latest_at']));

        return $result;
    }

    private function buildMessage(array $group): string
    {
        $count   = $group['count'];
        $actors  = $group['actors'];
        $first   = $actors[0]['name'] ?? 'Someone';
        $others  = $count - 1;

        return match ($group['type']) {
            'post_commented' => $count === 1
                ? "{$first} commented on your post"
                : "{$first} and {$others} other(s) commented on your post",
            'post_liked'     => $count === 1
                ? "{$first} liked your post"
                : "{$first} and {$others} other(s) liked your post",
            'post_shared'    => $count === 1
                ? "{$first} shared your artwork"
                : "{$first} and {$others} other(s) shared your artwork",
            default          => $count === 1
                ? "{$first} interacted with your post"
                : "{$count} people interacted with your post",
        };
    }
}
