<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Crypt;

class ProviderCredential extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'brand_id',
        'provider',
        'label',
        'use_for_ads',
        'is_default',
        'client_id',
        'client_secret',
        'access_token',
        'refresh_token',
        'ad_account_id',
        'scopes',
        'redirect_uri',
        'token_expires_at',
        'expiry_alert_sent',
        'status',
        'last_tested_at',
        'last_error',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'use_for_ads' => 'boolean',
        'is_default' => 'boolean',
        'scopes' => 'array',
        'token_expires_at' => 'datetime',
        'expiry_alert_sent' => 'boolean',
        'last_tested_at' => 'datetime',
    ];

    protected $hidden = [
        'client_secret',
        'access_token',
        'refresh_token',
    ];

    /**
     * The attributes that should be encrypted.
     */
    protected $encrypted = [
        'client_id',
        'client_secret',
        'access_token',
        'refresh_token',
        'ad_account_id',
    ];

    /**
     * Boot the model.
     */
    protected static function boot()
    {
        parent::boot();

        // Automatically encrypt sensitive fields on save
        static::saving(function ($model) {
            foreach ($model->encrypted as $field) {
                if ($model->isDirty($field) && !empty($model->$field)) {
                    // Only encrypt if not already encrypted
                    if (!str_starts_with($model->$field, 'eyJpdiI6')) {
                        $model->attributes[$field] = Crypt::encryptString($model->$field);
                    }
                }
            }
        });

        // When setting default, unset other defaults for same brand
        static::saving(function ($model) {
            if ($model->is_default && $model->use_for_ads) {
                static::where('brand_id', $model->brand_id)
                    ->where('provider', $model->provider)
                    ->where('id', '!=', $model->id)
                    ->update(['is_default' => false]);
            }
        });
    }

    /**
     * Get decrypted value for encrypted fields.
     */
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);

        if (in_array($key, $this->encrypted) && !empty($value)) {
            try {
                return Crypt::decryptString($value);
            } catch (\Exception $e) {
                // If decryption fails, return null
                return null;
            }
        }

        return $value;
    }

    /**
     * Get masked value for display (shows last 4 characters).
     */
    public function getMaskedAttribute($field)
    {
        $value = $this->getAttribute($field);
        
        if (empty($value)) {
            return null;
        }

        $length = strlen($value);
        if ($length <= 4) {
            return str_repeat('*', $length);
        }

        return str_repeat('*', $length - 4) . substr($value, -4);
    }

    /**
     * Check if token is expiring soon (within configured days).
     */
    public function isExpiringSoon($days = 7): bool
    {
        if (!$this->token_expires_at) {
            return false;
        }

        return $this->token_expires_at->lte(now()->addDays($days));
    }

    /**
     * Check if token is expired.
     */
    public function isExpired(): bool
    {
        if (!$this->token_expires_at) {
            return false;
        }

        return $this->token_expires_at->lte(now());
    }

    /**
     * Get the brand that owns the credential.
     */
    public function brand()
    {
        return $this->belongsTo(Brand::class);
    }

    /**
     * Get the user who created the credential.
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get the user who last updated the credential.
     */
    public function updater()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    /**
     * Scope to get only active credentials.
     */
    public function scopeActive($query)
    {
        return $query->where('status', 'connected');
    }

    /**
     * Scope to get credentials for ads.
     */
    public function scopeForAds($query)
    {
        return $query->where('use_for_ads', true);
    }

    /**
     * Scope to get expiring credentials.
     */
    public function scopeExpiring($query, $days = 7)
    {
        return $query->where('token_expires_at', '<=', now()->addDays($days))
            ->where('token_expires_at', '>', now());
    }

    /**
     * Scope to get expired credentials.
     */
    public function scopeExpired($query)
    {
        return $query->where('token_expires_at', '<=', now());
    }

    /**
     * Get provider display name.
     */
    public function getProviderDisplayNameAttribute(): string
    {
        return match($this->provider) {
            'youtube' => 'YouTube',
            'instagram' => 'Instagram',
            'tiktok' => 'TikTok',
            'linkedin' => 'LinkedIn',
            'twitter' => 'X (Twitter)',
            'facebook_ads' => 'Facebook Ads',
            'google_ads' => 'Google Ads',
            'custom' => 'Custom Provider',
            default => ucfirst($this->provider),
        };
    }

    /**
     * Get status badge color.
     */
    public function getStatusColorAttribute(): string
    {
        return match($this->status) {
            'connected' => 'green',
            'expiring' => 'yellow',
            'failed' => 'red',
            'disconnected' => 'gray',
            default => 'gray',
        };
    }
}