File: /home/xedaptot/ai.naniguide.com/app/Model/AdPlatform.php
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use App\Library\Traits\HasUid;
class AdPlatform extends Model
{
use HasFactory;
use HasUid;
// Platforms
const PLATFORM_META = 'meta';
const PLATFORM_GOOGLE = 'google';
const PLATFORM_TIKTOK = 'tiktok';
const PLATFORM_LINKEDIN = 'linkedin';
const PLATFORMS = [
self::PLATFORM_META,
self::PLATFORM_GOOGLE,
self::PLATFORM_TIKTOK,
self::PLATFORM_LINKEDIN,
];
const PLATFORM_LABELS = [
self::PLATFORM_META => 'Meta (Facebook/Instagram)',
self::PLATFORM_GOOGLE => 'Google Ads',
self::PLATFORM_TIKTOK => 'TikTok Ads',
self::PLATFORM_LINKEDIN => 'LinkedIn Ads',
];
// Statuses
const STATUS_ACTIVE = 'active';
const STATUS_EXPIRED = 'expired';
const STATUS_REVOKED = 'revoked';
const STATUS_ERROR = 'error';
// Health statuses
const HEALTH_HEALTHY = 'healthy';
const HEALTH_DEGRADED = 'degraded';
const HEALTH_ERROR = 'error';
const HEALTH_UNKNOWN = 'unknown';
protected $table = 'ad_platforms';
protected $fillable = [
'uid',
'customer_id',
'admin_id',
'platform',
'name',
'access_token',
'refresh_token',
'token_expires_at',
'platform_user_id',
'platform_user_name',
'scopes',
'last_health_check_at',
'health_status',
'health_message',
'metadata',
];
protected $casts = [
'access_token' => 'encrypted',
'refresh_token' => 'encrypted',
'token_expires_at' => 'datetime',
'last_health_check_at' => 'datetime',
'scopes' => 'array',
'metadata' => 'encrypted:array',
];
protected static function newFactory()
{
return \Database\Factories\AdPlatformFactory::new();
}
// Relations
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function admin()
{
return $this->belongsTo(Admin::class);
}
public function accounts()
{
return $this->hasMany(AdAccount::class);
}
public function activityLogs()
{
return $this->morphMany(AdActivityLog::class, 'loggable');
}
// Scopes
public function scopeOfCustomer($query, $customer)
{
return $query->where('customer_id', $customer->id);
}
public function scopeSystem($query)
{
return $query->whereNull('customer_id');
}
public function scopeActive($query)
{
return $query->where('status', self::STATUS_ACTIVE);
}
public function scopeOfPlatform($query, string $platform)
{
return $query->where('platform', $platform);
}
public function scopeHealthy($query)
{
return $query->where('health_status', self::HEALTH_HEALTHY);
}
public function scopeSearch($query, ?string $keyword)
{
if ($keyword) {
$query->where(function ($q) use ($keyword) {
$q->where('name', 'like', "%{$keyword}%")
->orWhere('platform_user_name', 'like', "%{$keyword}%");
});
}
return $query;
}
// Computed
public function getPlatformLabelAttribute(): string
{
return self::PLATFORM_LABELS[$this->platform] ?? $this->platform;
}
public function isHealthy(): bool
{
return $this->health_status === self::HEALTH_HEALTHY;
}
public function isTokenExpiring(int $daysThreshold = 7): bool
{
if (!$this->token_expires_at) {
return false;
}
return $this->token_expires_at->diffInDays(now()) <= $daysThreshold;
}
public function isTokenExpired(): bool
{
if (!$this->token_expires_at) {
return false;
}
return $this->token_expires_at->isPast();
}
public function isSystemPlatform(): bool
{
return $this->customer_id === null;
}
public function defaultAccount(): ?AdAccount
{
return $this->accounts()->where('is_default', true)->first();
}
}