<?php

namespace App\Models;

use App\Helpers\Helper;
use App\Models\Traits\Acceptable;
use App\Models\Traits\Searchable;
use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;
use Watson\Validating\ValidatingTrait;

/**
 * Model for Accessories.
 *
 * @version    v1.0
 */
class AccessoryCheckout extends Model
{
    use Searchable;

    protected $fillable = ['created_by', 'accessory_id', 'assigned_to', 'assigned_type', 'note'];
    protected $table = 'accessories_checkout';
    
    /**
     * Establishes the accessory checkout -> accessory relationship
     *
     * @author [A. Kroeger]
     * @since [v7.0.9]
     * @return \Illuminate\Database\Eloquent\Relations\Relation
     */
    public function accessory()
    {
        return $this->hasOne(\App\Models\Accessory::class, 'accessory_id');
    }

    /**
     * Establishes the accessory checkout -> user relationship
     *
     * @author [A. Kroeger]
     * @since [v7.0.9]
     * @return \Illuminate\Database\Eloquent\Relations\Relation
     */
    public function user()
    {
        return $this->hasOne(\App\Models\User::class, 'user_id');
    }

    /**
     * Get the target this asset is checked out to
     *
     * @author [A. Kroeger]
     * @since [v7.0]
     * @return \Illuminate\Database\Eloquent\Relations\Relation
     */
    public function assignedTo()
    {
        return $this->morphTo('assigned', 'assigned_type', 'assigned_to')->withTrashed();
    }

    /**
     * Gets the lowercased name of the type of target the asset is assigned to
     *
     * @author [A. Gianotto] [<snipe@snipe.net>]
     * @since [v4.0]
     * @return string
     */
    public function assignedType()
    {
        return $this->assigned_type ? strtolower(class_basename($this->assigned_type)) : null;
    }

    /**
     * Determines whether the accessory is checked out to a user
     *
     * Even though we allow allow for checkout to things beyond users
     * this method is an easy way of seeing if we are checked out to a user.
     *
     * @author [A. Kroeger]
     * @since [v7.0]
     */
    public function checkedOutToUser(): bool
    {
      return $this->assignedType() === Asset::USER;
    }

    public function scopeUserAssigned(Builder $query): void
    {
        $query->where('assigned_type', '=', User::class);
    }

    /**
     * Run additional, advanced searches.
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @param  array  $terms The search terms
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function advancedTextSearch(Builder $query, array $terms)
    {

        $userQuery = User::where(function ($query) use ($terms) {
            foreach ($terms as $term) {
                $search_str = '%' . $term . '%';
                $query->where('first_name', 'like', $search_str)
                    ->orWhere('last_name', 'like', $search_str)
                    ->orWhere('note', 'like', $search_str);
            }
        })->select('id');

        $locationQuery = Location::where(function ($query) use ($terms) {
            foreach ($terms as $term) {
                $search_str = '%' . $term . '%';
                $query->where('name', 'like', $search_str);
            }
        })->select('id');

        $assetQuery = Asset::where(function ($query) use ($terms) {
            foreach ($terms as $term) {
                $search_str = '%' . $term . '%';
                $query->where('name', 'like', $search_str);
            }
        })->select('id');

        $query->where(function ($query) use ($userQuery) {
            $query->where('assigned_type', User::class)
            ->whereIn('assigned_to', $userQuery);
        })->orWhere(function($query) use ($locationQuery) {
            $query->where('assigned_type', Location::class)
            ->whereIn('assigned_to', $locationQuery);
        })->orWhere(function($query) use ($assetQuery) {
            $query->where('assigned_type', Asset::class)
            ->whereIn('assigned_to', $assetQuery);
        })->orWhere(function($query) use ($terms) {
            foreach ($terms as $term) {
                $search_str = '%' . $term . '%';
                $query->where('note', 'like', $search_str);
            }
        });

        return $query;
    }


}