<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;

use App\Enums\UserRole;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Spatie\LaravelPasskeys\Models\Concerns\HasPasskeys;
use Spatie\LaravelPasskeys\Models\Concerns\InteractsWithPasskeys;

class User extends Authenticatable implements HasPasskeys
{
    use HasFactory, InteractsWithPasskeys, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var string[]
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'locale',
        // Discord
        'discord_id',
        'discord_avatar',
    ];

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

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        // Laravel defaults
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
        // Other
        'name' => 'string',
        'email' => 'string',
        'locale' => 'string',
        'roles' => 'array',
        'tag_blacklist' => 'array',
        // Discord
        'discord_id' => 'integer',
        'discord_avatar' => 'string',
    ];

    /**
     * Has Many Playlists.
     */
    public function playlists(): HasMany
    {
        return $this->hasMany(Playlist::class);
    }

    /**
     * Has Many Watched Episodes.
     */
    public function watched(): HasMany
    {
        return $this->hasMany(Watched::class);
    }

    /**
     * Has Many Watched Episodes.
     */
    public function likes(): int
    {
        return DB::table('markable_likes')->where('user_id', $this->id)->count();
    }

    /**
     * Has Many Comments.
     */
    public function comments()
    {
        return $this->hasMany(Comment::class, 'user_id');
    }

    /**
     * Get Comment Count.
     */
    public function commentCount(): int
    {
        return cache()->remember('userComments'.$this->id, 300, fn () => $this->comments->count());
    }

    /**
     * Returns the user avatar image url.
     */
    public function getAvatar(): string
    {
        if ($this->discord_id && $this->discord_avatar && ! $this->avatar) {
            return "https://external-content.duckduckgo.com/iu/?u={$this->discord_avatar}";
        }

        if ($this->avatar) {
            return Storage::url($this->avatar);
        }

        return asset('images/default-avatar.webp');
    }

    /**
     * Check if user has a specific role
     */
    public function hasRole(UserRole $role): bool
    {
        return in_array($role->value, $this->roles ?? [], true);
    }

    /**
     * Add Role to User
     */
    public function addRole(UserRole $role): void
    {
        if ($this->hasRole($role)) {
            return;
        }

        // Get all current roles
        $roles = $this->roles ?? [];

        // Add new role
        $roles[] = $role->value;

        $this->roles = $roles;
        $this->save();
    }

    /**
     * Remove Role from User
     */
    public function removeRole(UserRole $role): void
    {
        if (! $this->hasRole($role)) {
            return;
        }

        $this->roles = collect($this->roles)
            ->reject(fn ($value) => $value === $role->value)
            ->values()
            ->all();

        $this->save();
    }
}
