<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;

use Leenooks\Carbon;
use Leenooks\Traits\UserSwitch;
use App\Notifications\ResetPasswordNotification;

class User extends Authenticatable
{
    use HasApiTokens,Notifiable,UserSwitch;

	protected $dates = ['created_at','updated_at','last_access'];
	protected $with = ['accounts'];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

	protected $appends = [
		'surfirstname',
		'user_id_url',
	];
	protected $visible = [
		'id',
		'surfirstname',
		'level',
		'user_id_url',
	];

	public function accounts()
    {
		return $this->hasMany(Models\Account::class);
    }

	public function agents() {
		return $this->hasMany(static::class,'parent_id','id')->with('agents');
	}

	public function clients() {
		return $this->hasMany(static::class,'parent_id','id')->with('clients');
	}

	public function language()
	{
		return $this->belongsTo(Models\Language::class);
	}

	public function invoices()
	{
		return $this->hasManyThrough(Models\Invoice::class,Models\Account::class);
	}

	public function payments()
	{
		return $this->hasManyThrough(Models\Payment::class,Models\Account::class);
	}

	public function services()
	{
		return $this->hasManyThrough(Models\Service::class,Models\Account::class);
	}

	protected function supplier()
	{
		return $this->belongsTo(static::class,'parent_id','id');
	}

	protected function suppliers() {
		return $this->hasMany(static::class,'parent_id','id');
	}

	/**
	 * Logged in users full name
	 *
	 * @return string
	 */
	public function getFullNameAttribute()
	{
		return sprintf('%s %s',$this->firstname,$this->lastname);
	}

	public function getSurFirstNameAttribute()
	{
		return sprintf('%s, %s',$this->lastname,$this->firstname);
	}

	/**
	 * Return a Carbon Date if it has a value.
	 *
	 * @param $value
	 * @return \Leenooks\Carbon
	 * @todo This attribute is not in the schema
	 */
	public function getLastAccessAttribute($value)
	{
		if (! is_null($value))
			return new Carbon($value);
	}

	public function getInvoicesDueAttribute()
	{
		return $this->invoices
			->where('active',TRUE)
			->sortBy('id')
			->transform(function ($item) { if ($item->due > 0) return $item; })
			->reverse()
			->filter();
	}

	public function getLanguageAttribute($value)
	{
		if (is_null($this->language_id))
			return config('SITE_SETUP')->language;
		dd(__METHOD__,$value,config('SITE_SETUP')->language);
	}

	public function getPaymentHistoryAttribute()
	{
		return $this->payments
			->sortBy('date_payment')
			->reverse();
	}

	public function getServicesActiveAttribute()
	{
		return $this->services
			->where('active',TRUE);
	}

	/**
	 * @deprecated Use static::getFullNameAttribute()
	 * @return mixed
	 */
	public function getNameAttribute()
	{
		return $this->full_name;
	}

	public function getUserIdAttribute()
	{
		return sprintf('%02s-%04s',$this->site_id,$this->id);
	}

	public function getUserIdUrlAttribute()
	{
		return sprintf('<a href="/u/account/view/%s">%s</a>',$this->id,$this->user_id);
	}

	public function scopeActive()
	{
		return $this->where('active',TRUE);
	}

	public function isAdmin($id)
	{
		return $id AND in_array($this->role(),['wholesaler','reseller']) AND in_array($id,$this->all_accounts()->pluck('id')->toArray());
	}

	public function sendPasswordResetNotification($token)
	{
		$this->notify(new ResetPasswordNotification($token));
	}

	// List all the agents, including agents of agents
	public function all_agents($level=0)
	{
		$result = collect();

		foreach ($this->agents as $o)
		{
			if (! $o->active OR ! $o->agents->count())
				continue;

			$o->level = $level;

			$result->push($o);

			// Include agents of agents
			$result->push($o->all_agents($level+1));
		}

		return $result->flatten();
	}

	public function all_accounts()
	{
		$result = collect();

		foreach ($this->all_clients() as $o)
		{
			$result->push($o->accounts->where('active',TRUE));
		}

		return $result->flatten();
	}

	public function all_clients($level=0)
	{
		$result = collect();

		foreach ($this->clients as $o)
		{
			if (! $o->active)
				continue;

			$o->level = $level;

			$result->push($o);

			// Include clients of agents
			$result->push($o->all_clients($level+1));
		}

		return $result->flatten();
	}
	public function role()
	{
		// If I have agents and no parent, I am the wholesaler
		if (is_null($this->parent_id) AND $this->all_agents()->count())
			return 'wholesaler';

		// If I have agents and a parent, I am a reseller
		elseif ($this->parent_id AND $this->all_agents()->count())
			return 'reseller';

		// If I have no agents and a parent, I am a customer
		elseif (! $this->all_agents()->count())
			return 'customer';
	}
}