<?php

namespace Modules\WhatsApp\Entities;

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

class WaMessage extends Model
{
    protected $table = 'wa_messages';

    protected $fillable = [
        'business_id', 'channel_id', 'conversation_id', 'contact_id', 'wa_id',
        'direction', 'type', 'template_id', 'body', 'payload',
        'status', 'provider_message_id', 'error', 'attempts',
        'source', 'dedupe_key',
        'available_at', 'queued_at', 'sent_at', 'delivered_at', 'read_at',
        'created_by',
    ];

    protected $casts = [
        'payload'      => 'array',
        'attempts'     => 'integer',
        'available_at' => 'datetime',
        'queued_at'    => 'datetime',
        'sent_at'      => 'datetime',
        'delivered_at' => 'datetime',
        'read_at'      => 'datetime',
    ];

    public function channel(): BelongsTo
    {
        return $this->belongsTo(WaChannel::class, 'channel_id');
    }

    public function template(): BelongsTo
    {
        return $this->belongsTo(WaTemplate::class, 'template_id');
    }

    /** Outbound messages still owed to the recipient. */
    public function scopeUnsent($q)
    {
        return $q->where('direction', 'out')->whereIn('status', ['pending', 'queued']);
    }

    public function scopeForChannel($q, int $channelId)
    {
        return $q->where('channel_id', $channelId);
    }

    public function markSent(?string $providerId = null): void
    {
        $this->forceFill([
            'status'              => 'sent',
            'provider_message_id' => $providerId ?: $this->provider_message_id,
            'sent_at'             => now(),
            'error'               => null,
        ])->save();

        // A successful send proves the number is on WhatsApp.
        if ($this->direction === 'out') {
            WaContact::markWhatsApp((int) $this->business_id, (string) $this->wa_id, true);
        }
    }

    /** Permanent "this number isn't on WhatsApp" — fail + remember it. */
    public function markNotOnWhatsApp(string $error = 'Recipient is not a WhatsApp user.'): void
    {
        $this->forceFill(['status' => 'failed', 'error' => $error])->save();
        WaContact::markWhatsApp((int) $this->business_id, (string) $this->wa_id, false);
    }

    public function markFailed(string $error): void
    {
        $this->forceFill(['status' => 'failed', 'error' => $error])->save();
    }

    /** Hold the message for a later retry without consuming a "failure". */
    public function holdForRetry(string $reason, int $backoffSeconds): void
    {
        $this->forceFill([
            'status'       => 'pending',
            'error'        => $reason,
            'available_at' => now()->addSeconds($backoffSeconds),
        ])->save();
    }
}
