<?php

namespace App\Services\Roles;

use App\Models\Role;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;

class RoleQueryService
{
    public function listRoles(array $filters): LengthAwarePaginator
    {
        $query = Role::query()
            ->select('roles.*')
            ->leftJoin('user_roles', 'user_roles.role_id', '=', 'roles.id')
            ->selectRaw('COUNT(DISTINCT user_roles.user_id) AS user_count')
            ->groupBy('roles.id');

        if (!empty($filters['search'])) {
            $search = trim((string) $filters['search']);
            $query->where(function (Builder $q) use ($search) {
                $q->where('roles.name', 'like', '%' . $search . '%')
                    ->orWhere('roles.slug', 'like', '%' . $search . '%')
                    ->orWhere('roles.description', 'like', '%' . $search . '%');
            });
        }

        $sortBy = (string) ($filters['sort_by'] ?? 'name');
        $sortDir = strtolower((string) ($filters['sort_dir'] ?? 'asc')) === 'desc' ? 'desc' : 'asc';
        $allowed = ['name', 'slug', 'priority', 'is_active', 'created_at'];
        if (!in_array($sortBy, $allowed, true)) {
            $sortBy = 'name';
        }

        $perPage = (int) ($filters['per_page'] ?? 20);
        $perPage = $perPage > 0 ? $perPage : 20;

        return $query->orderBy($sortBy, $sortDir)->paginate($perPage);
    }

    public function listUsersWithRoles(array $filters): LengthAwarePaginator
    {
        $query = DB::table('users')
            ->leftJoin('user_roles', 'user_roles.user_id', '=', 'users.id')
            ->leftJoin('roles', 'roles.id', '=', 'user_roles.role_id')
            ->select(
                'users.id',
                'users.firstname',
                'users.lastname',
                'users.email',
                'users.account_id',
                DB::raw('GROUP_CONCAT(DISTINCT roles.name) as roles')
            )
            ->groupBy('users.id', 'users.firstname', 'users.lastname', 'users.email', 'users.account_id');

        if (!empty($filters['search'])) {
            $search = trim((string) $filters['search']);
            $query->where(function ($q) use ($search) {
                $q->where('users.firstname', 'like', '%' . $search . '%')
                    ->orWhere('users.lastname', 'like', '%' . $search . '%')
                    ->orWhere('users.email', 'like', '%' . $search . '%')
                    ->orWhere('users.account_id', 'like', '%' . $search . '%');
            });
        }

        $sortBy = (string) ($filters['sort_by'] ?? 'lastname');
        $sortDir = strtolower((string) ($filters['sort_dir'] ?? 'asc')) === 'desc' ? 'desc' : 'asc';
        $allowed = ['firstname', 'lastname', 'email', 'account_id'];
        if (!in_array($sortBy, $allowed, true)) {
            $sortBy = 'lastname';
        }

        $perPage = (int) ($filters['per_page'] ?? 20);
        $perPage = $perPage > 0 ? $perPage : 20;

        return $query->orderBy('users.' . $sortBy, $sortDir)->paginate($perPage);
    }
}
