<?php

declare(strict_types=1);

namespace App\Services\Messaging;

use App\Models\Conversation;
use App\Models\ConversationParticipant;
use App\Models\Message;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class MessageNotificationService
{
    public function __construct(
        private readonly MessagingPresenceService $presence,
    ) {}

    public function notifyNewMessage(Conversation $conversation, Message $message, User $sender): void
    {
        if (! DB::getSchemaBuilder()->hasTable('notifications')) {
            return;
        }

        $recipientIds = ConversationParticipant::query()
            ->where('conversation_id', $conversation->id)
            ->whereNull('left_at')
            ->where('user_id', '!=', $sender->id)
            ->where('is_muted', false)
            ->where('is_archived', false)
            ->pluck('user_id')
            ->all();

        if (empty($recipientIds)) {
            return;
        }

        $recipientRows = User::query()
            ->whereIn('id', $recipientIds)
            ->get()
            ->filter(fn (User $recipient) => $recipient->allowsMessagesFrom($sender))
            ->filter(function (User $recipient): bool {
                if (! (bool) config('messaging.notifications.offline_fallback_only', true)) {
                    return true;
                }

                return ! $this->presence->isUserOnline((int) $recipient->id);
            })
            ->pluck('id')
            ->map(fn ($id) => (int) $id)
            ->values()
            ->all();

        if (empty($recipientRows)) {
            return;
        }

        $preview = Str::limit((string) $message->body, 120, '…');
        $now = now();

        $rows = array_map(static fn (int $recipientId) => [
            'user_id' => $recipientId,
            'type' => 'message',
            'data' => json_encode([
                'conversation_id' => $conversation->id,
                'sender_id' => $sender->id,
                'sender_name' => $sender->username,
                'preview' => $preview,
                'message_id' => $message->id,
            ], JSON_UNESCAPED_UNICODE),
            'read_at' => null,
            'created_at' => $now,
            'updated_at' => $now,
        ], $recipientRows);

        DB::table('notifications')->insert($rows);
    }
}
