<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Support\Collection;

use App\Models\User;

use App\Events\WhisperCreated;

class Chat extends Model
{
    use HasFactory;
    use SoftDeletes;

    protected $hidden = ['user'];
    protected $appends = ['deleted', 'name'];
    protected $casts = [
        'selected' => 'boolean',
    ];

    public function saveChat($input)
    {
        $chat = new Chat();
        $chat->user_id = auth()->user()->id;
        $chat->room = Arr::get($input, 'room');
        $chat->message = Arr::get($input, 'message');
        $chat->reply_id = Arr::get($input, 'reply_id');

        $chat->save();

        $chat->append('name');

        return $chat;
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function reply()
    {
        return $this->belongsTo(Chat::class, 'reply_id');
    }

    public function getNameAttribute()
    {
        return $this->user->name;
    }

    public function getDeletedAttribute()
    {
        return $this->deleted_at ? true : false;
    }

    public static function canJoinRoom($room)
    {
        $room = explode('.', $room);

        $class_name = 'App\\Models\\'.Str::studly($room[0]);

        $object = resolve($class_name)->find($room[1]);

        if (!$object) {
            return false;
        }

        return auth()->user()->can('chat', $object);
    }

    public static function canModerateRoom($room)
    {
        $room = explode('.', $room);

        $class_name = 'App\\Models\\'.Str::studly($room[0]);

        $object = resolve($class_name)->find($room[1]);

        if (!$object) {
            return false;
        }

        return auth()->user()->can('moderate', $object);
    }

    public function whispers()
    {
        return $this->belongsToMany(User::class, 'whispers');
    }

    public static function findObject($room)
    {
        $data = explode('.', $room);
        $class = 'App\\Models\\'.Str::title($data[0]);
        $id = $data[1];

        return (new $class())->findOrFail($id);
    }

    public function getObject()
    {
        $data = explode('.', $this->room);
        $class = 'App\\Models\\'.Str::title($data[0]);
        $id = $data[1];

        return (new $class())->findOrFail($id);
    }

    public function sendWhisperToUsers($users)
    {
        if (!is_array($users) && $users instanceof User) {
            $users = collect([$users]);
        }

        foreach ($users as $user) {
            $this->whispers()->attach($user);
            broadcast(new WhisperCreated($this, $user));
        }

        return $this;
    }

    public function sendMessageToMods(Collection $mods)
    {
        $managers = User::whereHas('roles', function ($query) {
            return $query->where('name', 'admin')
                ->orWhere('name', 'livestreams-manager');
        })->get();

        $mods = $mods->merge($managers);

        if (auth()->check()) {
            $mods = $mods->filter(function ($mod) {
                return auth()->user()->id !== $mod->id;
            });
        }

        foreach ($mods as $mod) {
            $this->whispers()->attach($mod);
            broadcast(new WhisperCreated($this->load('whispers', 'reply'), $mod));
        }

        return $this;
    }
}
