<?php

namespace Helper;

use Exception;

class QueryBuilder
{
    public function __construct(private readonly string $tableName, private string $columns = '*') {}

    public function setColumns(string $columns): void
    {
        $this->columns = $columns;
    }

    /**
     * @throws Exception
     */
    public function select(array $filters = [], int $limit = 0): array
    {
        if (empty($filters)) {
            return ['sql' => "select {$this->columns} from {$this->tableName}"];
        }
        $where = [];
        $params = [];
        foreach ($filters as $filter) {
            [$name, $operation, $value] = explode(' ', $filter, 3);
            $placeholder = ":$name";
            $value = explode(' ', $value, 3);
            if (count($value) === 1) {
                $value = $value[0];
                if (is_numeric($value)) {
                    $value = (int)$value;
                }
            } else {
                array_walk_recursive($value, function (&$var) {
                    if (is_numeric($var)) {
                        $var = (int)$var;
                    }
                });
                if (is_numeric($value[0]) && is_numeric($value[2])) {
                    $value = match ($value[1]) {
                        '+' => $value[0] + $value[2],
                        '-' => $value[0] - $value[2],
                        '*' => $value[0] * $value[2],
                        '/' => ($value[2] != 0) ? $value[0] / $value[2] : throw new Exception('Деление на ноль недопустимо.'),
                        default => throw new Exception('Недопустимый оператор. Допустимы: +, -, *, /.'),
                    };
                } elseif (is_string($value[0])) {
                    $placeholder = "$value[0] $value[1] :$name";
                    $value = $value[2];
                } elseif (is_string($value[2])) {
                    $placeholder = "$value[2] $value[1] :$name";
                    $value = $value[0];
                }
            }
            //todo: но есть ещё форменное скотство, когда в запрос кидают сложные формулы...

            $where[] = "$name $operation $placeholder";
            $params[$name] = $value;
        }

        return [
            'sql' => "select $this->columns from $this->tableName where " . implode(" and ", $where) . ($limit > 0 ? " limit $limit" : ""),
            'binds' => $params,
        ];
    }
}