<?php

namespace Modules\User\Models;

use App\Models\Trait\HasCode;
use App\Services\Upload\UploadService;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Modules\Country\Models\Country;
use Modules\Product\Models\Favorite;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\Unit\Models\Unit;
use Modules\User\Enums\UserRoleEnum;

/**
 * @property mixed role
 * @property mixed Modules
 */
class User extends Authenticatable
{
    use Notifiable;
    use SoftDeletes;
    use HasCode;

    public function __construct(array $attributes = [] )
    {
        parent::__construct($attributes);
    }
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'last_name',
        'email',
        'phone',
        'birth_date',
        'gender',
        'photo',
        'password',
        'role',
    ];

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

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    protected static function booted()
    {
        // dd(auth()->user()->role);
        //
        static::creating(function ($user) {
            $user->phone = validatePhone($user->phone);
            $user->email = $user->email?:null;
        });
        static::updating(function ($user) {
            $user->phone = validatePhone($user->phone);
            $user->email = $user->email?:null;
        });
    }

    public function address()
    {
        return $this->belongsTo(Address::class)->withTrashed();
    }


    /**
     * Get the modules of this user
     * 
     * @return Module|Collection
     */
    public function getModules()
    {
        // Get Modules Current User can access
        if ($this->role == UserRoleEnum::SUPER_ADMIN->value) {
            return Module::orderBy('sort')->get();
        } elseif ($this->role == UserRoleEnum::ADMIN->value) {
            return Module::orderBy('sort')->get();
        } else  {
            return $this->modules()->orderBy('sort')->get();
        }
    }
    /**
     * Get the Modules of this user
     * @return BelongsToMany
     */
    public function modules(): BelongsToMany
    {
        return $this->belongsToMany(Module::class, 'user_modules');
    }

    /**
     * Check if the user can access a module
     * @param string, module name
     * @return bool
     */
    public function hasModule($module): bool
    {
        if ($this->getModules()->contains('path', $module)) {
            return true;
        }
        return false;
    }

    /**
     * Check if the user can access a module
     * @param string, module name
     * @return bool
     */
    public function canAccess($module)
    {
        // dd($module);
        return $this->hasModule($module);
    }
    
    public function providerProfile()
    {
        return $this->hasOne(UserProviderProfile::class);
    }
    
    public function units()
    {
        return $this->hasMany(Unit::class);
    }
    
    public function soldUnits()
    {
        return $this->hasMany(Unit::class)->where('sold_status', config('globals.sold_status') );
    }

    public function favorited($product_id)
    {
        $account = $this->accountService->getAccount();
        $favorite = $this->hasOne(Favorite::class)->where('user_status',$account['status'])->where('user_id',$this->id)->where('product_id',$product_id)->first();
        return $favorite;
    }

    public function country()
    {
        return $this->belongsTo(Country::class)->withTrashed();
    }

    public function setPasswordAttribute($value)
    {
        if($value)
        {
            $this->attributes['password'] = bcrypt($value);
        }
        else
        {
            $this->attributes['password'] = $this->password;
        }
    }
    public function setPhotoAttribute($value)
    {
        if($value)
        {
            if(is_string($value))
            {
                $this->attributes['photo'] = $value;
            }
            else
            {
                $oldPhoto= 'logo.png' != $this->photo ?  $this->photo : null;
                $photo = UploadService::upload($value, $oldPhoto, 'users');
                $this->attributes['photo'] = $photo;
            }
        }
        else
        {
            $this->attributes['photo'] = request()->method() == 'post'  ? 'logo.png' : $this->photo;
        }
    }
    
    /**
     * Check User may be deleted
     * used in grid view in users module
     * @return bool
     */
    public function getDisableDeleteAttribute()
    {
        if($this->is_admin) {
            return true;
        }
        if($this->id == request()->user()->id){
            return true;
        }
        if ($this->is_provider) {
            return ($this->total_units ?? $this->units()->withTrashed()->count()) > 0;
        }
        
        return false ;
    }
    
    public function getIsAdminAttribute()
    {
        return in_array($this->role , [UserRoleEnum::SUPER_ADMIN->value, UserRoleEnum::ADMIN->value]);
    }

    /**
     * Check if User is Moderator
     * @return bool
     */
    
    public function getIsModeratorAttribute()
    {
        return in_array($this->role , UserRoleEnum::admins());
    }
    
    /**
     * Check if User is provider
     * @return bool
     */
    public function getIsProviderAttribute()
    {
        return in_array($this->role , UserRoleEnum::providers());
    }
    
    /**
     * Check if User is user member
     * @return bool
     */
    public function getIsProviderAdminAttribute()
    {
        return $this->role == UserRoleEnum::PROVIDER->value;
    }
    
    /**
     * Check if User is user member
     * @return bool
     */
    public function getIsUserAttribute()
    {
        return $this->role == UserRoleEnum::USER->value;
    }
    
    /**
     * Check Phone Code
     * @return bool
     */
    public function getPhoneCodeAttribute()
    {
        return config('globals.phone_code');
        return $this->country_id ? Country::where('id', $this->country_id)->first()->phonecode : null;
    }

    /**
     * Check Phone without Code
     * @return bool
     */
    public function getPurePhoneAttribute()
    {
        return preg_replace(config('globals.phone_regex'), '$2', $this->phone);
    }

    /**
     * Return Photo URL
     * @return string|null
     */
    public function getPhotoUrlAttribute() : ?string
    {
        // dd(UploadService::url($this->photo), $this->photo);
        return UploadService::url($this->photo);
    }

    /**
     * Return status text
     * @return string|null
     */
    public function getStatusTextAttribute() : ?string
    {
        $status= ($this->status ?? $this->providerProfile->status ?? config('globals.default_user_status'));
        return __('providers.statuses.'.$status);
    }

    /**
     * Return badges
     * @return string|null
     */
    public function getBadgesAttribute() : array
    {
        $badges = [];
        // dd($this->providerProfile);
        if ($this->providerProfile->is_top) {
            $badges[] = __('providers.badges_labels.top');
        }
        if ($this->providerProfile->is_reliable) {
            $badges[] = __('providers.badges_labels.reliable');
        }
        if ($this->is_most_active ?? null) {
            $badges[] = __('providers.badges_labels.most_active_user_units_month');
        }
        return $badges;
    }

    /**
     * Return badges text
     * @return string|null
     */
    public function getBadgesTextAttribute() : ?string
    {
        $badges = $this->badges;
        return $badges ? implode(' <br/> ', $badges) : null;
    }

    /**
     * Return total units visits
     * @return string|null
     */
    public function getTotalUnitsVisitsAttribute() : ?string
    {
        return $this->units()->sum('visits');
    }
}
