<?php

namespace App\Traits;

use Illuminate\Http\Request;

/**
 * Helper para aplicar búsqueda, ordenamiento, paginación y relaciones
 * 
 * Configuración en el modelo:
 * - $searchable: Columnas para búsqueda de texto
 * - $sortable: Columnas para ordenar
 * - $allowedIncludes: Relaciones que se pueden cargar
 * 
 * Uso en controlador:
 * $this->applyQuery(Role::class, $request)
 * 
 * Parámetros disponibles:
 * - search: Busca en columnas searchable
 * - sort_by: Ordena por columna sortable
 * - order: asc o desc
 * - page: Número de página
 * - per_page: Items por página (máximo 100)
 * - include: Relaciones a cargar
 */
trait ApiQueryTraitxx
{
    public function applyQuery($model, Request $request, int $defaultPerPage = 15)
    {
        // Crear una instancia temporal para acceder a las propiedades
        $instance = new $model();

        // Obtener configuración del modelo
        $searchableColumns = $instance->searchable ?? [];
        $sortableColumns = $instance->sortable ?? ['id'];
        $allowedIncludes = $instance->allowedIncludes ?? [];

        // Validación dinámica de sort_by
        $sortByValidation = !empty($sortableColumns)
            ? 'sometimes|string|in:' . implode(',', $sortableColumns)
            : 'sometimes|string';

        // Validar parámetros
        $validated = $request->validate([
            'page' => 'sometimes|integer|min:1',
            'per_page' => 'sometimes|integer|min:1|max:100',
            'search' => 'sometimes|string|max:255',
            'sort_by' => $sortByValidation,
            'order' => 'sometimes|string|in:asc,desc',
            'include' => 'sometimes|string|max:255',
        ]);

        // Iniciar query
        $query = $model::query();

        // Aplicar relaciones (include)
        if ($request->filled('include') && !empty($allowedIncludes)) {
            $requestedIncludes = array_map('trim', explode(',', $request->include));
            $validIncludes = array_intersect($requestedIncludes, $allowedIncludes);

            if (!empty($validIncludes)) {
                $query->with($validIncludes);
            }
        }

        // Aplicar búsqueda
        if ($request->filled('search') && !empty($searchableColumns)) {
            $search = $request->search;
            $query->where(function ($q) use ($search, $searchableColumns) {
                foreach ($searchableColumns as $column) {
                    $q->orWhere($column, 'LIKE', '%' . $search . '%');
                }
            });
        }

        // Aplicar ordenamiento
        $sortBy = $request->get('sort_by', $sortableColumns[0] ?? 'id');
        $order = $request->get('order', 'asc');

        if (in_array($sortBy, $sortableColumns)) {
            $query->orderBy($sortBy, $order);
        }

        // Sin paginación (retornar todos los resultados)
        if (!$request->has('page')) {
            return $query->get();
        }

        // Con paginación
        $perPage = (int) $request->get('per_page', $defaultPerPage);
        $perPage = min($perPage, 100); // Asegurar máximo 100

        return $query->paginate($perPage, ['*'], 'page', $request->page);
    }
}
