<?php

namespace App\Models;

use App\Classes\General\Interfaces\Addressable;
use App\Classes\General\Interfaces\Contactable;
use App\Classes\General\Interfaces\Packable;
use App\Classes\General\Interfaces\Remarkable;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Scopes\CustomerOrdersScope;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;

class Order extends AbstractModel implements Addressable, Packable, Remarkable
{
    use SoftDeletes;

    protected $table = 'orders';

    protected $dates = ['deleted_at'];


    /**
     * @return BelongsTo
     */
    public function companyModule(): belongsTo
    {
        return $this->belongsTo(CompanyModule::class, 'company_module_id', 'id');
    }

    /**
     * @return MorphMany
     */
    public function orderSteps(): morphMany
    {
        return $this->morphMany(Step::class, 'owner');
    }

    /**
     * @return MorphMany
     */
    public function addresses(): morphMany
    {
        return $this->morphMany(Address::class, 'owner');
    }

    /**
     * @return MorphMany
     */
    public function packingLists(): morphMany
    {
        return $this->morphMany(PackingList::class, 'owner');
    }

    /**
     * @return MorphMany
     */
    public function remarks(): morphMany
    {
        return $this->morphMany(Remark::class, 'owner');
    }

    /**
     * @return HasManyThrough
     */
    public function parcels(): HasManyThrough
    {
        return $this->HasManyThrough(Package::class, PackingList::class, 'owner_id', 'packing_list_id')->where('owner_type', Order::class);
    }

    /**
     * @return HasMany
     */
    public function OrderRoles(): HasMany
    {
        return $this->HasMany(OrderRole::class, 'order_id');
    }


    protected static function booted()
    {
//        if (auth()->user()->type === RoleTypes::USER) {
//            static::addGlobalScope(new CustomerOrdersScope);
//        }
    }

    public function addressesPendingVerification()
    {
        return $this->addresses()->where('status','=',ApprovalStatus::PENDING_VERIFICATION);
    }

    public function addressesApproved()
    {
        return $this->addresses()->where('status','=',ApprovalStatus::APPROVED);
    }

    public function originWarehousePackages()
    {
        return $this->parcels()->shippingList()
            ->whereDoesntHave('shippingSchedules',
                function($schedule) {
                    return $schedule->dispatched()
                        ->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                }
            );
    }

    public function inTransitPackages()
    {
        return $this->parcels()->shippingList()->Shipping()
            ->whereHas('shippingSchedules',
                function($schedule) {
                    return $schedule->dispatched()
                        ->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                }
            )
            ->whereDoesntHave('container', function($container) {
                return $container->where('containers.status', ApprovalStatus::COMPLETED);
            }
        );
    }

    public function destinationWarehousePackages()
    {
        return $this->parcels()->shippingList()
            ->whereHas('container',
                function($container) {
                    return $container->where('containers.status', ApprovalStatus::COMPLETED);
                }
            )
            ->whereDoesntHave('deliverySchedules',
                function($schedule) {
                    return $schedule->dispatched()->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                }
            );
    }

    public function deliveredPackages()
    {
        return $this->parcels()->shippingList()
            ->whereHas('deliverySchedules',
                function($schedule) {
                    return $schedule->dispatched()->whereIn('schedules.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
                }
            );
    }

    /**
     * @return morphMany
     */
    public function transactions(): morphMany
    {
        return $this->morphMany(Transaction::class, 'owner');
    }
}
