<?php

namespace App\Helpers\Ecommerce\Product\Sort;

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

class ProductSorter
{
    /*
     * Query builder
     */
    protected mixed $queryBuilder;

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

    /**
     * Allowed columns for sorting
     *
     * @var array<string>
     */
    protected array $allowedColumns = [
        'price_amount',
        'created_at',
        'name',
    ];

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

    /**
     * Construct statically
     */
    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(), [
            'sorting' => ['nullable', 'string', new SortableColumnRule($this->allowedColumns)],
        ]);
    }

    /**
     * Sort from request
     */
    public function sort()
    {
        if ($this->request->isNotFilled('sorting') || $this->validateRequest()->fails()) {
            return $this->orderByLatest();
        }

        return $this->queryBuilder->orderBy($this->getColumn(), $this->getSortType());
    }

    /**
     * Get sort column
     */
    public function getColumn(): string
    {
        return explode('-', $this->request->sorting)[0];
    }

    /**
     * Get sort type
     */
    public function getSortType(): string
    {
        $sortType = explode('-', $this->request->sorting)[1];

        return $sortType === 'descending' ? 'DESC' : 'ASC';
    }

    /**
     * Order by latest (created_at)
     */
    public function orderByLatest(): mixed
    {
        return $this->queryBuilder->latest();
    }
}
