<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class NotificationDelivery extends Model
{
    use HasFactory;

    protected $fillable = [
        'notification_id',
        'user_id',
        'device_token',
        'delivered_at',
        'opened_at',
        'clicked_at',
        'status',
        'error_message',
        'delivery_metadata'
    ];

    protected $casts = [
        'delivered_at' => 'datetime',
        'opened_at' => 'datetime',
        'clicked_at' => 'datetime',
        'delivery_metadata' => 'array',
    ];

    /**
     * Get the notification that owns the delivery.
     */
    public function notification(): BelongsTo
    {
        return $this->belongsTo(Notification::class);
    }

    /**
     * Get the user that owns the delivery.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Mark the notification as delivered.
     */
    public function markAsDelivered(string $deviceToken): bool
    {
        return $this->update([
            'device_token' => $deviceToken,
            'delivered_at' => now(),
            'status' => 'delivered',
            'error_message' => null
        ]);
    }

    /**
     * Mark the notification as opened.
     */
    public function markAsOpened(): bool
    {
        return $this->update([
            'opened_at' => now(),
            'status' => 'opened'
        ]);
    }

    /**
     * Mark the notification as clicked.
     */
    public function markAsClicked(): bool
    {
        return $this->update([
            'clicked_at' => now(),
            'status' => 'clicked'
        ]);
    }

    /**
     * Mark the notification as failed.
     */
    public function markAsFailed(string $errorMessage): bool
    {
        return $this->update([
            'status' => 'failed',
            'error_message' => $errorMessage
        ]);
    }

    /**
     * Check if the notification was delivered successfully.
     */
    public function wasDelivered(): bool
    {
        return $this->status === 'delivered' || $this->status === 'opened' || $this->status === 'clicked';
    }

    /**
     * Check if the notification was opened.
     */
    public function wasOpened(): bool
    {
        return $this->status === 'opened' || $this->status === 'clicked';
    }

    /**
     * Check if the notification was clicked.
     */
    public function wasClicked(): bool
    {
        return $this->status === 'clicked';
    }

    /**
     * Check if the notification failed to deliver.
     */
    public function failed(): bool
    {
        return $this->status === 'failed';
    }

    /**
     * Get the delivery status label.
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            'pending' => 'Pending',
            'delivered' => 'Delivered',
            'opened' => 'Opened',
            'clicked' => 'Clicked',
            'failed' => 'Failed',
            default => 'Unknown'
        };
    }

    /**
     * Get the delivery rate (time between scheduled and delivered).
     */
    public function getDeliveryRateAttribute(): ?float
    {
        if (!$this->delivered_at || !$this->notification->scheduled_at) {
            return null;
        }

        return $this->delivered_at->diffInSeconds($this->notification->scheduled_at);
    }

    /**
     * Get the engagement rate (whether user opened or clicked).
     */
    public function getEngagementRateAttribute(): float
    {
        if (!$this->wasDelivered()) {
            return 0.0;
        }

        return $this->wasClicked() ? 2.0 : ($this->wasOpened() ? 1.0 : 0.0);
    }
}
