<?php
namespace Incoviba\Common\Implement\Database\Query;

use Incoviba\Common\Define;
use Incoviba\Common\Ideal;

class Insert extends Ideal\Query implements Define\Query\Insert
{
    protected string $table;
    protected array $columns;
    protected array $values;
    protected Define\Query\Select $select;

    public function into(string $table, ?array $columns = null): Insert
    {
        $this->table = $table;
        if ($columns !== null) {
            return $this->columns($columns);
        }
        return $this;
    }
    public function columns(array $columns): Insert
    {
        foreach ($columns as $column) {
            $this->addColumn($column);
        }
        return $this;
    }
    public function values(array $values): Insert
    {
        foreach ($values as $value) {
            $this->addValue($value);
        }
        return $this;
    }
    public function select(Define\Query\Select $select): Insert
    {
        $this->select = $select;
        return $this;
    }
    public function build(): string
    {
        $query = [
            "INSERT INTO {$this->table}"
        ];
        if (isset($this->select)) {
            $query []= " {$this->select}";
            return implode('', $query);
        }
        $query []= $this->getColumns();
        $query []= $this->getValues();
        return implode('', $query);
    }

    protected function addColumn(string $column): Insert
    {
        if (!isset($this->columns)) {
            $this->columns = [];
        }
        $this->columns []= $column;
        return $this;
    }
    protected function addValue(mixed $value): Insert
    {
        if (!isset($this->values)) {
            $this->values = [];
        }
        $this->values []= $value;
        return $this;
    }
    protected function getColumns(): string
    {
        return ' (' . implode(', ', array_map(function(string $column) {return "`{$column}`";}, $this->columns)) . ')';
    }
    protected function getValues(): string
    {
        return ' VALUES (' . implode(', ', array_map(function($value) {
            if ($value === '?') {
                return $value;
            }
            if ($value === (int) $value) {
                return $value;
            }
            if (str_starts_with($value, ':')) {
                return $value;
            }
            return "'{$value}'";
        }, $this->values)) . ')';
    }
}
