<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
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\Relations\MorphTo;
use Illuminate\Support\Str;

class Subscription extends Model
{
    use HasFactory;

    protected $guarded = ['id'];

    protected $appends = ['total_price'];

    protected $casts = [
        'status' => 'integer',
        'start_date' => 'datetime',
        'end_date' => 'datetime',
        'trial_start_date' => 'datetime',
        'trial_end_date' => 'datetime',
        'next_billing_date' => 'datetime',
        'current_period_start' => 'datetime',
        'current_period_end' => 'datetime',
        'billing_cycle' => 'integer',
        'billing_cycle_count' => 'integer',
    ];

    protected static function booted(): void
    {
        static::creating(function ($subscription) {
            do {
                $reference = setting('subscription.subscription_id_prefix', 'SUB') . '-' . Str::upper(Str::random(10));
            } while (self::where('reference_id', $reference)->exists());

            $subscription->reference_id = $reference;
        });
    }

    public function orders()
    {
        return $this->hasMany(Order::class)->orderBy('created_at', 'desc');
    }

    // last order
    public function lastOrder()
    {
        return $this->orders()->latest()->first();
    }

    // get last completed order
    public function lastActiveOrder()
    {
        return $this->orders()->where('status', getConstant('ORDER_STATUS_COMPLETED'))->latest()->first();
    }

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

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

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

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

    public function logs()
    {
        return $this->hasMany(SubscriptionLog::class);
    }

    public function purchasable(): MorphTo
    {
        return $this->morphTo();
    }

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

    public function getPurchasedPlan()
    {
        return $this->items()->whereHas('purchasable', function ($query) {
            $query->where('purchasable_type', PricingTier::class);
        })->first();
    }

    // add total price + addons total price
    protected function totalPrice(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->price + $this->addons->sum('total_price'),
        );
    }

    public function toArray()
    {
        $array = parent::toArray();
        $array['trial_duration_unit_label'] = $this->trial_duration_unit_label;
        $array['billing_cycle_label'] = $this->billing_cycle_label;
        return $array;
    }
}
