<?php

namespace App\Services;

use App\Models\User;
use App\Models\UserNotification;
use Illuminate\Support\Collection;

class InAppNotificationService
{
    public function __construct(
        private readonly PushNotificationService $pushService,
        private readonly EmailNotificationService $emailService,
    ) {}

    public function notifyUser(
        int $userId,
        string $type,
        string $title,
        string $body,
        array $payload = [],
    ): UserNotification {
        $notification = UserNotification::create([
            'user_id' => $userId,
            'type' => $type,
            'title' => $title,
            'body' => $body,
            'payload' => $payload ?: null,
        ]);

        $this->pushService->notifyUser($userId, $title, $body, $payload);
        $this->emailService->notifyUserById($userId, $title, $body, $payload);

        return $notification;
    }

    public function notifyUsers(
        Collection $users,
        string $type,
        string $title,
        string $body,
        array $payload = [],
    ): void {
        $userIds = $users
            ->pluck('id')
            ->filter(static fn ($id): bool => is_numeric($id))
            ->map(static fn ($id): int => (int) $id)
            ->unique()
            ->values();

        if ($userIds->isEmpty()) {
            return;
        }

        $now = now();
        $encodedPayload = $payload
            ? json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
            : null;

        $rows = $userIds->map(static function (int $userId) use ($type, $title, $body, $encodedPayload, $now): array {
            return [
                'user_id' => $userId,
                'type' => $type,
                'title' => $title,
                'body' => $body,
                'payload' => $encodedPayload,
                'created_at' => $now,
                'updated_at' => $now,
            ];
        })->all();

        UserNotification::insert($rows);

        foreach ($userIds as $userId) {
            $this->pushService->notifyUser($userId, $title, $body, $payload);
            $this->emailService->notifyUserById($userId, $title, $body, $payload);
        }
    }

    public function notifyAllLiners(
        string $type,
        string $title,
        string $body,
        array $payload = [],
    ): void {
        $liners = User::query()
            ->where('role', 'liner')
            ->where('is_available', true)
            ->select('id')
            ->get();

        $this->notifyUsers($liners, $type, $title, $body, $payload);
    }
}
