<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laravel\Cashier\Subscription;

class Service extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'user_id',
        'subscription_id',
        'plan_id',
        'service_type',
        'platform',
        'platform_service_id',
        'status',
        'ipv4_address',
        'ipv6_address',
        'hostname',
        'domain',
        'credentials',
        'provisioned_at',
        'suspended_at',
        'terminated_at',
        'auto_renew',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'credentials',
    ];

    /**
     * The accessors to append to the model's array form.
     *
     * @var list<string>
     */
    protected $appends = [
        'provisioning_info',
    ];

    protected function casts(): array
    {
        return [
            'credentials' => 'encrypted:array',
            'provisioned_at' => 'datetime',
            'suspended_at' => 'datetime',
            'terminated_at' => 'datetime',
            'auto_renew' => 'boolean',
        ];
    }

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

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

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

    public function provisioningLogs(): HasMany
    {
        return $this->hasMany(ProvisioningLog::class);
    }

    public function bandwidthUsage(): HasMany
    {
        return $this->hasMany(BandwidthUsage::class);
    }

    public function isActive(): bool
    {
        return $this->status === 'active';
    }

    /**
     * Get safe provisioning info excluding sensitive fields like passwords and keys.
     *
     * @return array<string, mixed>|null
     */
    public function getProvisioningInfoAttribute(): ?array
    {
        $credentials = $this->credentials;

        if (! is_array($credentials) || empty($credentials)) {
            return null;
        }

        $sensitiveKeys = [
            'password',
            'secret',
            'token',
            'api_key',
            'api_secret',
            'private_key',
            'ssh_key',
            'ssh_password',
            'root_password',
            'admin_password',
            'database_password',
            'ftp_password',
        ];

        return collect($credentials)
            ->reject(fn (mixed $value, string $key): bool => in_array(strtolower($key), $sensitiveKeys, true))
            ->toArray();
    }
}
