<?php

namespace Modules\User\Models\Traits;

use Catch\CatchAdmin;
use Catch\Support\Module\ModuleRepository;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Route;
use Modules\Permissions\Models\Permissions;

trait UserRelations
{
    protected bool $isPermissionModuleEnabled = false;

    /**
     * init traits
     */
    public function initializeUserRelations(): void
    {
        $this->isPermissionModuleEnabled = app(ModuleRepository::class)->enabled('permissions');

        if ($this->isPermissionModuleEnabled) {
            $this->with = ['roles', 'jobs'];
        }
    }

    /**
     * roles
     *
     * @return BelongsToMany
     */
    public function roles(): BelongsToMany
    {
        return $this->belongsToMany($this->getRolesModel(), 'user_has_roles', 'user_id', 'role_id');
    }

    /**
     * jobs
     *
     * @return BelongsToMany
     */
    public function jobs(): BelongsToMany
    {
        return $this->belongsToMany($this->getJobsModel(), 'user_has_jobs', 'user_id', 'job_id');
    }


    /**
     * permissions
     */
    public function withPermissions(): self
    {
        if (! $this->isPermissionModuleEnabled) {
            return $this;
        }

        /* @var Permissions $permissionsModel */
        $permissionsModel = app($this->getPermissionsModel())->where('hidden',1)->orderByDesc('sort');

        if ($this->isSuperAdmin()) {
            $permissions = $permissionsModel->get();
        } else {
            $permissions = Collection::make();
            $roleIds = $this->roles()->pluck('role_id')->toArray();
            app($this->getRolesModel())->whereIn('id', $roleIds)->with(['permissions' => function($query){
                return $query->where('hidden',1)->orderByDesc('sort');
            }])->get()
                ->each(function ($role) use (&$permissions) {
                    $permissions = $permissions->concat($role->permissions);
                });
            $permissions = $permissions->unique('id');
        }

        $this->setAttribute('permissions', $permissions->each(fn ($permission) => $permission->setAttribute('hidden', $permission->isHidden())));

        return $this;
    }

    /**
     *
     * permission module controller.action
     *
     * @param string|null $permission
     * @return bool
     */
    public function can(string $permission = null): bool
    {

        if (! $this->isPermissionModuleEnabled) {
            return true;
        }

        if ($this->isSuperAdmin()) {
            return true;
        }

        $this->withPermissions();

        $actions = Collection::make();

        $this->getAttribute('permissions')->each(function ($permission) use (&$actions) {
            if ($permission->isAction()) {
                [$controller, $action] = explode('@', $permission->permission_mark);

                $actions->add(strtolower(CatchAdmin::getModuleControllerNamespace($permission->module).$controller.'Controller@'.$action));
            }
        });

        if ($permission) {
            [$module, $controller, $action] = explode('@', $permission);

            $permission = strtolower(CatchAdmin::getModuleControllerNamespace($module).$controller.'Controller@'.$action);
        }else{
            $permission =  strtolower(Route::currentRouteAction());
        }

        return $actions->contains($permission);
    }

    /**
     * get RolesModel
     *
     * @see \Modules\Permissions\Models\Roles
     * @return string
     */
    protected function getRolesModel(): string
    {
        return '\\'.CatchAdmin::getModuleModelNamespace('permissions').'Roles';
    }


    /**
     * get JobsModel
     *
     * @see \Modules\Permissions\Models\Jobs
     * @return string
     */
    protected function getJobsModel(): string
    {
        return '\\'.CatchAdmin::getModuleModelNamespace('permissions').'Jobs';
    }

    /**
     * get PermissionsModel
     *
     * @return string
     *@see \Modules\Permissions\Models\Permissions
     */
    protected function getPermissionsModel(): string
    {
        return '\\'.CatchAdmin::getModuleModelNamespace('permissions').'Permissions';
    }
}