<?php

namespace App\Repositories;

use App\Models\Notification;

class NotificationRepository extends BaseRepository
{
    public function __construct(Notification $model)
    {
        parent::__construct($model);
    }

    /**
     * Get the list of recipient categories a user is authorized to see.
     * Hierarchy: Developer > Administrator > User > all
     */
    public function getAuthorizedRecipients($user)
    {
        $recipients = ['all'];

        if ($user->hasRole('Developer')) {
            return ['Developer', 'Administrator', 'User', 'all'];
        }

        if ($user->hasRole('Administrator')) {
            return ['Administrator', 'User', 'all'];
        }

        // Default: only see notifications for 'User' and 'all'
        return ['User', 'all'];
    }

    /**
     * Get ALL notifications for a user based on their roles,
     * BUT exclude those they have personally deleted/hidden.
     */
    public function getActiveNotificationsForUser($user, $offset = 0, $limit = 10)
    {
        $query = $this->model->query();

        // 1. Filter by roles (Broadcast targeting) hierarchical
        $authorizedRecipients = $this->getAuthorizedRecipients($user);
        $query->whereIn('recipient', $authorizedRecipients);

        // 2. Left Join personal interactions
        $query->leftJoin('system_notification_user', function ($join) use ($user) {
            $join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
                ->where('system_notification_user.user_id', '=', $user->id);
        });

        // 3. Exclude personally deleted ones
        $query->whereNull('system_notification_user.deleted_at');

        // 4. Select needed columns (avoiding ID collision with Join)
        return $query->select('system_notifications.*', 'system_notification_user.read_at as personal_read_at')
            ->latest('system_notifications.created_at')
            ->skip($offset)
            ->take($limit)
            ->get();
    }

    /**
     * Get personal unread count.
     */
    public function getUnreadCount($user)
    {
        $query = $this->model->query();

        // Target filtering hierarchical
        $authorizedRecipients = $this->getAuthorizedRecipients($user);
        $query->whereIn('recipient', $authorizedRecipients);

        // Join to check read/deleted status
        $query->leftJoin('system_notification_user', function ($join) use ($user) {
            $join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
                ->where('system_notification_user.user_id', '=', $user->id);
        });

        // Unread = (Global read_at is null AND Personal read_at is null) AND not deleted
        $query->whereNull('system_notification_user.read_at')
            ->whereNull('system_notification_user.deleted_at');

        return $query->count();
    }

    /**
     * Personal Mark As Read
     */
    public function markAsRead($notificationId, $userId)
    {
        \DB::table('system_notification_user')->updateOrInsert(
            ['notification_id' => $notificationId, 'user_id' => $userId],
            ['read_at' => now(), 'updated_at' => now()]
        );
    }

    /**
     * Personal Delete (Hide)
     */
    public function personalDelete($notificationId, $userId)
    {
        \DB::table('system_notification_user')->updateOrInsert(
            ['notification_id' => $notificationId, 'user_id' => $userId],
            ['deleted_at' => now(), 'updated_at' => now()]
        );
    }

    /**
     * Mark ALL visible notifications as read for this user.
     */
    public function markAllAsReadForUser($user)
    {
        $authorizedRecipients = $this->getAuthorizedRecipients($user);

        // 1. Get IDs of notifications that are visible to user but either:
        // - Have no entry in pivot (meaning unread)
        // - Have an entry with read_at IS NULL and deleted_at IS NULL
        $unreadIds = $this->model->query()
            ->whereIn('recipient', $authorizedRecipients)
            ->leftJoin('system_notification_user', function ($join) use ($user) {
                $join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
                    ->where('system_notification_user.user_id', '=', $user->id);
            })
            ->whereNull('system_notification_user.read_at')
            ->whereNull('system_notification_user.deleted_at')
            ->pluck('system_notifications.id');

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

        // 2. Perform batch updateOrInsert for each (or just loop if small, but let's stick to markAsRead helper)
        foreach ($unreadIds as $id) {
            $this->markAsRead($id, $user->id);
        }
    }
}
