<?php

namespace App\Models;

use App\Enums\SubscriptionStatus;
use App\Models\Concerns\BelongsToBusiness;
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 Illuminate\Support\Str;

class Subscription extends Model
{
    use BelongsToBusiness, HasFactory, SoftDeletes;

    protected $fillable = [
        'business_id',
        'plan_id',
        'status',
        'billing_cycle',
        'starts_at',
        'trial_ends_at',
        'renews_at',
        'ends_at',
        'cancelled_at',
        'price',
        'currency',
        'gateway',
        'gateway_subscription_id',
        'usage_snapshot',
        'meta',
    ];

    protected function casts(): array
    {
        return [
            'starts_at' => 'datetime',
            'status' => SubscriptionStatus::class,
            'trial_ends_at' => 'datetime',
            'renews_at' => 'datetime',
            'ends_at' => 'datetime',
            'cancelled_at' => 'datetime',
            'price' => 'decimal:2',
            'usage_snapshot' => 'array',
            'meta' => 'array',
        ];
    }

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

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

    public function getStatusLabelAttribute(): string
    {
        return $this->status instanceof SubscriptionStatus
            ? $this->status->label()
            : Str::headline((string) $this->status);
    }

    public function getStatusValueAttribute(): string
    {
        return $this->status instanceof SubscriptionStatus ? $this->status->value : (string) $this->status;
    }

    public function getStatusBadgeVariantAttribute(): string
    {
        return $this->status instanceof SubscriptionStatus ? $this->status->badgeVariant() : 'muted';
    }

    public function isActiveLike(): bool
    {
        return in_array($this->status_value, [
            SubscriptionStatus::Active->value,
            SubscriptionStatus::Trial->value,
        ], true) && ! $this->isExpired();
    }

    public function isTrial(): bool
    {
        return $this->status_value === SubscriptionStatus::Trial->value;
    }

    public function isExpired(): bool
    {
        if ($this->status_value === SubscriptionStatus::Expired->value) {
            return true;
        }

        return $this->ends_at?->isPast() || ($this->isTrial() && $this->trial_ends_at?->isPast());
    }

    public function trialEndsSoon(int $days = 3): bool
    {
        return $this->isTrial()
            && $this->trial_ends_at
            && $this->trial_ends_at->isFuture()
            && $this->trial_ends_at->lte(now()->addDays($days));
    }
}
