<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Mtc\MercuryDataModels\Traits\EnsuresSlug;
use OwenIt\Auditing\Contracts\Auditable;

class NotificationMap extends Model implements Auditable
{
    use HasFactory;
    use EnsuresSlug;
    use \OwenIt\Auditing\Auditable;

    /**
     * Slugs already served by fixed inbound notification routes. A map must not use
     * one of these, or its inbound URL would be shadowed by the fixed route.
     */
    public const RESERVED_SLUGS = [
        'autograb',
        'auto-trader-hub',
        'auto-imaging',
        'autos-on-show',
        'sales-force',
    ];

    protected $fillable = [
        'name',
        'slug',
        'type',
        'active',
        'template_id',
        'field_map',
        'validation',
        'config',
    ];

    protected $casts = [
        'active' => 'boolean',
        'field_map' => 'array',
        'validation' => 'array',
        'config' => 'array',
    ];

    #[\Override]
    protected static function boot(): void
    {
        parent::boot();

        self::saving(static function (self $notificationMap) {
            $notificationMap->ensureSlug();
        });
    }

    /**
     * The system-level template this map was derived from, if any.
     */
    public function template(): ?NotificationTemplate
    {
        return $this->template_id
            ? NotificationTemplate::find($this->template_id)
            : null;
    }

    /**
     * Stable key used to namespace this map's rows in the shared pending-notification
     * drain (pending_provider_notifications.provider). Keyed by id so it always fits
     * the provider column regardless of slug length.
     */
    public function providerKey(): string
    {
        return 'notification-map:' . $this->id;
    }

    /**
     * Resolve a notification map from a provider key produced by providerKey().
     */
    public static function fromProviderKey(string $providerKey): ?self
    {
        if (!str_starts_with($providerKey, 'notification-map:')) {
            return null;
        }

        return self::find((int) substr($providerKey, strlen('notification-map:')));
    }

    /**
     * Public inbound endpoint that external systems post stock updates to.
     */
    public function getInboundUrl(): ?string
    {
        if (empty($this->slug)) {
            return null;
        }

        return url('/api/notifications/' . tenant('id') . '/' . $this->slug);
    }

    /**
     * OpenAPI documentation endpoint for this notification's inbound payload.
     */
    public function getDocsUrl(): ?string
    {
        $inbound = $this->getInboundUrl();

        return $inbound ? $inbound . '/docs' : null;
    }

    /**
     * Scope to filter by active state.
     */
    public function scopeActive(Builder $query, $value = null): void
    {
        if (in_array($value, [0, 1], true)) {
            $query->where('active', $value);
        }
    }

    public function getConfig(string $key, $default = null)
    {
        return $this->config[$key] ?? $default;
    }
}
