<?php

namespace App\Models;

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

/**
 * Tenant-level, UI-configurable CRM lead export. Defines where captured leads are
 * POSTed (url + headers + secret) and how the outbound JSON payload is shaped:
 * either PASSTHROUGH (form field names as-is) or MAPPED (an explicit target field
 * list whose names become the per-question mapping options in the form builder).
 *
 * Outbound counterpart of NotificationMap; mirrors the ExportMap connection pattern
 * (credentials stored on the row, secret encrypted).
 */
class LeadExport extends Model implements Auditable
{
    use HasFactory;
    use EnsuresSlug;
    use \OwenIt\Auditing\Auditable;

    /** Send each answer under its form field name; no per-question mapping. */
    public const MODE_PASSTHROUGH = 'passthrough';

    /** Send answers against an explicit target field list, mapped per question. */
    public const MODE_MAPPED = 'mapped';

    public const MODES = [
        self::MODE_PASSTHROUGH,
        self::MODE_MAPPED,
    ];

    /** Short, human-facing explanation of each mode for the admin UI. */
    public const MODE_DESCRIPTIONS = [
        self::MODE_PASSTHROUGH => 'Sends every form answer using its own field name. No per-question mapping needed.',
        self::MODE_MAPPED => 'Sends answers against a defined set of CRM fields. Map each form question to a field.',
    ];

    /**
     * Mode options for the admin UI, each with a friendly label and short description.
     *
     * @return array<int, array<string, string>>
     */
    public static function modeOptions(): array
    {
        return [
            [
                'id' => self::MODE_PASSTHROUGH,
                'name' => 'Passthrough',
                'description' => self::MODE_DESCRIPTIONS[self::MODE_PASSTHROUGH],
            ],
            [
                'id' => self::MODE_MAPPED,
                'name' => 'Mapped',
                'description' => self::MODE_DESCRIPTIONS[self::MODE_MAPPED],
            ],
        ];
    }

    /** Prefix for the synthetic form-action key and per-question mapping key. */
    public const PROVIDER_PREFIX = 'lead-export:';

    protected $fillable = [
        'name',
        'slug',
        'type',
        'active',
        'format',
        'mode',
        'url',
        'password',
        'headers',
        'field_map',
        'config',
        'template_id',
        'uuid',
    ];

    protected $casts = [
        'active' => 'boolean',
        'password' => 'encrypted',
        'headers' => 'array',
        'field_map' => 'array',
        'config' => 'array',
    ];

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

        self::creating(static function (self $leadExport) {
            if (empty($leadExport->uuid)) {
                $leadExport->uuid = Str::uuid()->toString();
            }
        });

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

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

    /**
     * Stable key that namespaces this export in config('crm.form_actions') and in each
     * form question's per-provider mapping (FormQuestion->data[providerKey]). Keyed by
     * id so slug edits never orphan question mappings.
     */
    public function providerKey(): string
    {
        return self::PROVIDER_PREFIX . $this->id;
    }

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

        return self::find((int) substr($providerKey, strlen(self::PROVIDER_PREFIX)));
    }

    /**
     * Friendly display label for an enquiry/form action name. Lead-export actions
     * resolve to the export's own name; every other action falls back to the
     * title-cased action key (e.g. "send-to-salesforce" => "Send To Salesforce").
     */
    public static function actionLabel(string $actionName): string
    {
        $fallback = Str::title(str_replace('-', ' ', $actionName));

        if (!str_starts_with($actionName, self::PROVIDER_PREFIX)) {
            return $fallback;
        }

        return self::fromProviderKey($actionName)?->name ?? $fallback;
    }

    /**
     * OpenAPI documentation endpoint describing this export's outbound payload.
     * Path-based tenancy so the link resolves the tenant from the URL and works when
     * opened directly (the admin API relies on the X-Tenant header instead).
     */
    public function getDocsUrl(): ?string
    {
        if (empty($this->slug)) {
            return null;
        }

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

    public function isMapped(): bool
    {
        return $this->mode === self::MODE_MAPPED;
    }

    /**
     * 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;
    }
}
