<?php

namespace App\Models\Solicitor;

use App\Contracts\Communications\CommunicationSender;
use App\Enum\Contact\MessageChannel;
use App\Trait\BelongsToSolicitor;
use App\ValueObjects\PhoneNumber;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
 * A whitelisted sender identity used for outbound SMS.  Two flavours:
 *
 *   - 'number'     — a real phone number (E.164 normalized in normalized_value)
 *   - 'alpha_tag'  — a 1-11 char alphanumeric sender ID (no inbound replies)
 *
 * Distinct from SolicitorPhoneNumber, which is owned by the dialler / voice
 * domain.  Only entries in this table can be used as the SMS "from" identity.
 */
class SolicitorSmsSender extends Model implements CommunicationSender
{
    use BelongsToSolicitor;

    public const TYPE_NUMBER = 'number';
    public const TYPE_ALPHA_TAG = 'alpha_tag';

    protected $table = 'solicitor_sms_senders';

    protected $fillable = [
        'solicitor_id',
        'label',
        'type',
        'value',
        'normalized_value',
        'provider',
        'twilio_account_sid',
        'twilio_subaccount_sid',
        'twilio_phone_number_sid',
        'is_active',
        'is_default',
        'supports_replies',
        'meta',
    ];

    protected $casts = [
        'is_active' => 'boolean',
        'is_default' => 'boolean',
        'supports_replies' => 'boolean',
        'meta' => 'array',
    ];

    public function scopeActive(Builder $q): Builder
    {
        return $q->where('is_active', true);
    }

    public function scopeOfType(Builder $q, string $type): Builder
    {
        return $q->where('type', $type);
    }

    public function isAlphaTag(): bool
    {
        return $this->type === self::TYPE_ALPHA_TAG;
    }

    public function isNumber(): bool
    {
        return $this->type === self::TYPE_NUMBER;
    }

    /**
     * Normalize the value before save.  For numbers, store E.164 in
     * normalized_value; for alpha tags, store the value as-is and clear
     * normalized_value.
     */
    public static function booted(): void
    {
        static::saving(function (self $sender) {
            if ($sender->type === self::TYPE_NUMBER) {
                $phone = PhoneNumber::tryFrom($sender->value);
                $sender->normalized_value = $phone?->toE164();
                $sender->supports_replies = true;
            } else {
                $sender->normalized_value = null;
                $sender->supports_replies = false;
            }
        });
    }

    /* ---------------- CommunicationSender contract ---------------- */

    public function id(): int
    {
        return (int) $this->attributes['id'];
    }

    public function label(): string
    {
        $shown = $this->isAlphaTag()
            ? $this->value
            : ($this->normalized_value ?? $this->value);

        return "{$this->label} ({$shown})";
    }

    public function value(): string
    {
        return (string) ($this->normalized_value ?? $this->value);
    }

    public function channel(): MessageChannel
    {
        return MessageChannel::SMS;
    }

    public function replyTo(): ?string
    {
        return null;
    }

    public function signatureHtml(): ?string
    {
        return null;
    }

    public function signatureText(): ?string
    {
        return null;
    }

    public function providerConfig(): array
    {
        return [
            'provider' => $this->provider,
            'twilio_account_sid' => $this->twilio_account_sid,
            'twilio_subaccount_sid' => $this->twilio_subaccount_sid,
            'twilio_phone_number_sid' => $this->twilio_phone_number_sid,
            'type' => $this->type,
            'supports_replies' => $this->supports_replies,
        ];
    }
}
