<?php

namespace App\Models;

use App\Enums\GuestNotificationAudience;
use App\Enums\GuestNotificationState;
use App\Enums\GuestNotificationType;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;

/**
 * @property array<string, mixed>|null $payload
 */
class GuestNotification extends Model
{
    /** @use HasFactory<\Database\Factories\GuestNotificationFactory> */
    use HasFactory;

    protected $fillable = [
        'tenant_id',
        'event_id',
        'type',
        'title',
        'body',
        'payload',
        'audience_scope',
        'target_identifier',
        'status',
        'priority',
        'expires_at',
    ];

    protected function casts(): array
    {
        return [
            'payload' => 'array',
            'expires_at' => 'datetime',
            'type' => GuestNotificationType::class,
            'audience_scope' => GuestNotificationAudience::class,
            'status' => GuestNotificationState::class,
        ];
    }

    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    public function event(): BelongsTo
    {
        return $this->belongsTo(Event::class);
    }

    public function receipts(): HasMany
    {
        return $this->hasMany(GuestNotificationReceipt::class);
    }

    public function scopeForEvent(Builder $query, Event $event): void
    {
        $query->where('event_id', $event->getKey());
    }

    public function scopeActive(Builder $query): void
    {
        $query->where('status', GuestNotificationState::ACTIVE->value);
    }

    public function scopeNotExpired(Builder $query): void
    {
        $query->where(function (Builder $builder) {
            $builder->whereNull('expires_at')->orWhere('expires_at', '>', Carbon::now());
        });
    }

    public function scopeVisibleToGuest(Builder $query, ?string $guestIdentifier): void
    {
        $query->where(function (Builder $builder) use ($guestIdentifier) {
            $builder->where('audience_scope', GuestNotificationAudience::ALL->value);

            if ($guestIdentifier) {
                $builder->orWhere(function (Builder $inner) use ($guestIdentifier) {
                    $inner->where('audience_scope', GuestNotificationAudience::GUEST->value)
                        ->where('target_identifier', $guestIdentifier);
                });
            }
        });
    }

    public function hasExpired(): bool
    {
        return $this->expires_at instanceof Carbon && $this->expires_at->isPast();
    }
}
