<?php

namespace App\Models;

use App\Services\AI\MetaAdLibraryProvider;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

#[Fillable(['user_id', 'platform', 'external_ad_id', 'snapshot', 'thumbnail_path', 'search_query'])]
class CompetitorAdReference extends Model
{
    /**
     * The snapshot, with any access token removed on the way in and out.
     *
     * This replaces an `array` cast rather than sitting beside one: a cast and an
     * accessor for the same attribute conflict, and the cast would win.
     *
     * `MetaAdLibraryProvider` used to complete Meta's bare `&access_token` with
     * the product's own token, so this column holds credentials in rows written
     * before that was fixed, and the creative wizard renders the URL as an
     * `<a href>`. Stripping on read means those rows stop leaking without a data
     * migration; stripping on write means a provider that regresses cannot put
     * one back.
     *
     * The column is left as it is on disk. Rewriting history here would hide how
     * many rows were affected, and that is worth knowing before the token is
     * rotated.
     */
    protected function snapshot(): Attribute
    {
        return Attribute::make(
            get: fn (?string $value): ?array => $this->redacted(
                is_string($value) ? json_decode($value, true) : null,
            ),
            set: fn (mixed $value): ?string => is_array($value)
                ? json_encode($this->redacted($value))
                : (is_string($value) ? $value : null),
        );
    }

    /**
     * @return array<string, mixed>|null
     */
    private function redacted(mixed $snapshot): ?array
    {
        if (! is_array($snapshot)) {
            return null;
        }

        foreach (['ad_snapshot_url', 'adLibraryUrl'] as $field) {
            if (is_string($snapshot[$field] ?? null)) {
                $snapshot[$field] = MetaAdLibraryProvider::withoutAccessToken($snapshot[$field]);
            }
        }

        return $snapshot;
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}
