<?php

namespace App\Http\Traits;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

/**
 * Trait for applying common filters to queries.
 * 
 * Provides methods to filter, search and sort Eloquent queries.
 * 
 * @example
 * use App\Http\Traits\FiltersQueries;
 * 
 * class ExampleController extends Controller
 * {
 *     use FiltersQueries;
 * 
 *     public function index(Request $request)
 *     {
 *         $query = Example::query();
 *         $query = $this->applyFilters($query, $request, ['name', 'description']);
 *         return $query->paginate(15);
 *     }
 * }
 */
trait FiltersQueries
{
    /**
     * Apply common filters to a query.
     *
     * @param Builder $query The query builder
     * @param Request $request The request with filter parameters
     * @param array $searchFields Fields to search in
     * @param string $searchParam The request parameter for search (default: 'search')
     * @return Builder
     */
    protected function applyFilters(Builder $query, Request $request, array $searchFields = ['name'], string $searchParam = 'search'): Builder
    {
        // Apply search filter
        if ($request->filled($searchParam)) {
            $search = $request->input($searchParam);
            $query->where(function (Builder $q) use ($search, $searchFields) {
                foreach ($searchFields as $field) {
                    $q->orWhere($field, 'like', "%{$search}%");
                }
            });
        }

        // Apply status filter
        if ($request->filled('status')) {
            $status = $request->input('status');
            if ($status === 'active') {
                $query->where('is_active', true);
            } elseif ($status === 'inactive') {
                $query->where('is_active', false);
            }
        }

        // Apply category filter
        if ($request->filled('category')) {
            $query->where('category', $request->input('category'));
        }

        // Apply date range filter
        if ($request->filled('from_date')) {
            $query->whereDate('created_at', '>=', $request->input('from_date'));
        }

        if ($request->filled('to_date')) {
            $query->whereDate('created_at', '<=', $request->input('to_date'));
        }

        return $query;
    }

    /**
     * Apply sorting to a query.
     *
     * @param Builder $query The query builder
     * @param Request $request The request with sort parameters
     * @param string $defaultSort Default sort field
     * @param string $defaultDirection Default sort direction
     * @return Builder
     */
    protected function applySorting(
        Builder $query, 
        Request $request, 
        string $defaultSort = 'created_at', 
        string $defaultDirection = 'desc'
    ): Builder {
        $sortField = $request->input('sort', $defaultSort);
        $sortDirection = $request->input('direction', $defaultDirection);

        // Validate direction
        $sortDirection = in_array(strtolower($sortDirection), ['asc', 'desc']) 
            ? strtolower($sortDirection) 
            : $defaultDirection;

        return $query->orderBy($sortField, $sortDirection);
    }

    /**
     * Apply pagination with query string preservation.
     *
     * @param Builder $query The query builder
     * @param int $perPage Items per page
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    protected function paginateWithQueryString(Builder $query, int $perPage = 15)
    {
        return $query->paginate($perPage)->withQueryString();
    }

    /**
     * Apply all common filters, sorting and pagination.
     *
     * @param Builder $query The query builder
     * @param Request $request The request
     * @param array $searchFields Fields to search in
     * @param int $perPage Items per page
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    protected function filterSortAndPaginate(
        Builder $query, 
        Request $request, 
        array $searchFields = ['name'], 
        int $perPage = 15
    ) {
        $query = $this->applyFilters($query, $request, $searchFields);
        $query = $this->applySorting($query, $request);
        return $this->paginateWithQueryString($query, $perPage);
    }
}
