<?php

namespace App\Models;

use Database\Factories\SubscriptionFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

#[Fillable([
    'user_id',
    'user_email_snapshot',
    'plan_id',
    'currency_id',
    'provider_key',
    'provider_subscription_id',
    'status',
    'period',
    'trial_ends_at',
    'current_period_starts_at',
    'current_period_ends_at',
    'canceled_at',
    'cancels_at_period_end',
    'renewal_reminder_for_period_end',
    'seats',
    'is_test',
])]
class Subscription extends Model
{
    /** @use HasFactory<SubscriptionFactory> */
    use HasFactory;

    protected function casts(): array
    {
        return [
            'trial_ends_at' => 'datetime',
            'current_period_starts_at' => 'datetime',
            'current_period_ends_at' => 'datetime',
            'renewal_reminder_for_period_end' => 'datetime',
            'canceled_at' => 'datetime',
            'cancels_at_period_end' => 'boolean',
            'seats' => 'integer',
            'is_test' => 'boolean',
        ];
    }

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

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

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

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

    public function isActive(): bool
    {
        if (! in_array($this->status, ['active', 'trialing', 'past_due'], true)) {
            return false;
        }

        if ($this->canceled_at === null) {
            return true;
        }

        if ($this->cancels_at_period_end
            && $this->current_period_ends_at !== null
            && $this->current_period_ends_at->isFuture()
        ) {
            return true;
        }

        return false;
    }

    public function feature(string $key, mixed $default = null): mixed
    {
        return $this->plan?->feature($key, $default) ?? $default;
    }
}
