<?php

namespace App\Modules\Settings\Rbac\Repositories;

use App\Modules\Settings\Rbac\Models\Role;
use App\Support\Lists\ListQuery;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;

class RoleRepository
{
    public function forTenant(int $tenantId): Collection
    {
        return Role::query()
            ->where('tenant_id', $tenantId)
            ->withCount(['permissions', 'users'])
            ->orderBy('name')
            ->get();
    }

    public function paginateForIndex(int $tenantId, Request $request): LengthAwarePaginator
    {
        $query = Role::query()
            ->where('tenant_id', $tenantId)
            ->withCount(['permissions', 'users']);

        ListQuery::applySearch($query, $request->input('q'), ['name', 'description']);
        ListQuery::applyBoolean($query, 'is_active', $request->input('is_active'));
        ListQuery::applySort(
            $query,
            $request->input('sort'),
            $request->input('dir'),
            [
                'name' => 'name',
                'is_active' => 'is_active',
            ],
            'name',
        );

        return ListQuery::paginate($query, $request);
    }

    public function activeForTenant(int $tenantId): Collection
    {
        return Role::query()
            ->where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->orderBy('name')
            ->get();
    }

    public function findForTenant(int $tenantId, int $roleId): ?Role
    {
        return Role::query()
            ->where('tenant_id', $tenantId)
            ->where('id', $roleId)
            ->with('permissions')
            ->withCount('users')
            ->first();
    }

    public function findBySlug(int $tenantId, string $slug): ?Role
    {
        return Role::query()
            ->where('tenant_id', $tenantId)
            ->where('slug', $slug)
            ->where('is_active', true)
            ->first();
    }

    public function slugExists(int $tenantId, string $slug): bool
    {
        return Role::withTrashed()
            ->where('tenant_id', $tenantId)
            ->where('slug', $slug)
            ->exists();
    }

    public function hasAssignedUsers(Role $role): bool
    {
        return $role->users()->exists();
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function create(array $data): Role
    {
        return Role::query()->create($data);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function update(Role $role, array $data): Role
    {
        $role->update($data);

        return $role;
    }

    public function delete(Role $role): void
    {
        $role->delete();
    }

    public function refresh(Role $role): Role
    {
        return $role->fresh(['permissions'])->loadCount('users');
    }
}
