<?php

namespace App\Helpers\Ecommerce\Product\Filter;

use App\Rules\CommaSeparatedIntegers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class ProductFilterer
{
    /*
     * Query builder
     */
    protected $queryBuilder;

    /**
     * Request
     */
    protected Request $request;

    /**
     * Product filterer
     */
    public function __construct($queryBuilder, $request)
    {
        $this->queryBuilder = $queryBuilder;
        $this->request = $request;
    }

    /**
     * Create "new" class via static method
     */
    public static function make($queryBuilder, $request): self
    {
        return new self($queryBuilder, $request);
    }

    /**
     * Validate the request
     */
    public function validateRequest(): \Illuminate\Contracts\Validation\Validator
    {
        return Validator::make($this->request->all(), [
            'ids' => ['nullable', 'string', new CommaSeparatedIntegers()],
            'brands' => ['nullable', 'string', new CommaSeparatedIntegers()],
            'categories' => ['nullable', 'string', new CommaSeparatedIntegers()],
            'name' => ['nullable', 'string', 'max:255'],
            'min_price' => ['nullable', 'numeric'],
            'max_price' => ['nullable', 'numeric'],
            'backorder' => ['nullable', 'in:0,1'],
        ]);
    }

    /**
     * Sort
     */
    public function filter()
    {
        if ($this->validateRequest()->fails()) {
            return $this->queryBuilder;
        }

        if ($this->request->filled('brands')) {
            $this->queryBuilder->whereIntegerInRaw('products.brand_id', explode(',', $this->request->brands));
        }

        if ($this->request->filled('categories')) {
            $this->queryBuilder->whereIn(
                column: 'id',
                values: (
                    fn ($query) => $query->from('product_has_relations')
                        ->select('product_id')
                        ->distinct('product_id')
                        ->where('productable_type', '=', 'category')
                        ->whereIn('productable_id', explode(',', $this->request->categories))
                )
            );
        }

        if ($this->request->filled('name')) {
            $this->queryBuilder->where('products.name', 'ilike', $this->request->name.'%');
        }

        if ($this->request->filled('min_price')) {
            $this->queryBuilder->whereRaw('products.price_amount::NUMERIC >= ?', [$this->request->float('min_price')]);
        }

        if ($this->request->filled('max_price')) {
            $this->queryBuilder->whereRaw('products.price_amount::NUMERIC <= ?', [$this->request->float('max_price')]);
        }

        if ($this->request->filled('backorder')) {
            $this->queryBuilder->where('products.backorder', $this->request->backorder);
        }

        return $this->queryBuilder;
    }
}
