<?php

namespace App\Models\Registries;

use App\Models\Asset;
use App\Support\HasObjectsTrait;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class Entry extends Model {
    use UuidScopeTrait, SoftDeletes, HasObjectsTrait, RelationValuesTrait;

    protected $table = 'registry_entries';

    protected $dates = [
        'active_since',
        'active_till',
        'suspended_since',
        'suspended_till',
        'cancelled_at'
    ];

    protected $fillable = [
        'uuid',
        'registry_id',
        'category_id',
        'asset_id',
        'number',
        'name',
        'active_since',
        'active_till',
        'suspended_since',
        'suspended_till',
        'cancelled_at'
    ];

    protected $hidden = [
        'id'
    ];


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

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

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

    public function operations(): MorphToMany {
        return $this->objectsByGroup('operations');
    }


    public function scopeByStates($query, $states) {
        $query->where(function($query) use($states) {
            collect($states)->each(function($state) use($query) {
                $query->orWhere(function($query) use($state) {
                    $query->$state();
                });
            });
        });
    }

    public function scopeAwaiting($query) {
        $query->where('active_since', '>', now());
    }
    public function scopeActive($query) {
        $query->where('active_since', '<=', now())->where(function($query) {
            $query->whereNull('active_till')->orWhere('active_till', '>', now());
        })->notCancelled()->notSuspended();
    }
    public function scopeExpired($query) {
        $query->where('active_till', '<=', now());
    }
    public function scopeSuspended($query) {
        $query->where('suspended_since', '<=', now())->where(function($query) {
            $query->whereNull('suspended_till')->orWhere('suspended_till', '>', now());
        })->notCancelled();
    }
    public function scopeNotSuspended($query) {
        $query->where(function($query) {
            $query->whereNull('suspended_since')->orWhere('suspended_since', '>', now());
        })->where(function($query) {
            $query->whereNull('suspended_till')->orWhere('suspended_till', '<', now());
        });
    }
    public function scopeCancelled($query) {
        $query->where('cancelled_at', '<=', now());
    }
    public function scopeNotCancelled($query) {
        $query->where(function($query) {
            $query->whereNull('cancelled_at')->orWhere('cancelled_at', '>', now());
        });
    }



    public function getPropertiesAttribute(): ?Model {
        return ($type = $this->registry->parsedType['options']['properties'] ?? null) ? $this->getObject($type, 'properties') : null;
    }

    public function getStateAttribute(): ?array {
        $state = null;
        if ($this->active_since) {
            $state = ($this->active_since <= now()) ? EntryState::ACTIVE : EntryState::AWAITING;
            if ($this->active_till && ($this->active_till <= now())) $state = EntryState::EXPIRED;
            elseif ($this->cancelled_at && ($this->cancelled_at <= now())) $state = EntryState::CANCELLED;
            elseif ($this->suspended_since && ($this->suspended_since <= now()) && (!$this->suspended_till || ($this->suspended_till > now()))) $state = EntryState::SUSPENDED;
        }
        return $state ? ['name' => $state, 'title' => EntryState::TITLES[$state] ?? null] : null;
    }


    public function sortOperations() {
        $this->operations()->reorder()->applyOrders(['order-date' => 'desc'])->get()->each(function($operation, $ord) {
            $this->objects()->updateExistingPivot($operation, ['ord' => $ord]);
        });
    }



}
