<?php
namespace ProVM\Implement\Data\Query\Create;

use ProVM\Define\Query\Create\CreateDefinition;

class Definition implements CreateDefinition
{
    protected string $name;
    protected string $type;
    protected int $size;
    protected bool $primary;
    protected bool $auto_increment;
    protected bool $unsigned;
    protected mixed $default;
    protected string $foreign_table;
    protected string $foreign_key;
    protected int $foreign_delete;
    protected int $foreign_update;

    public function name(string $name): CreateDefinition
    {
        $this->name = $name;
        return $this;
    }
    public function type(string $type, ?int $size = null): CreateDefinition
    {
        $this->type = $type;
        if ($size !== null) {
            $this->size = $size;
        }
        return $this;
    }
    public function primary(): CreateDefinition
    {
        $this->primary = true;
        return $this;
    }
    public function autoIncrement(): CreateDefinition
    {
        $this->auto_increment = true;
        return $this;
    }
    public function unsigned(): CreateDefinition
    {
        $this->unsigned = true;
        return $this;
    }
    public function default(mixed $value): CreateDefinition
    {
        $this->default = $value;
        return $this;
    }
    public function foreign(string $reference_table, string $reference_column = 'id', int $on_delete = CreateDefinition::CASCADE, int $on_update = CreateDefinition::CASCADE): CreateDefinition
    {
        $this->foreign_table = $reference_table;
        $this->foreign_key = $reference_column;
        $this->foreign_delete = $on_delete;
        $this->foreign_update = $on_update;
        return $this;
    }

    public function __toString(): string
    {
        $type = $this->type ?? 'int';
        if (isset($this->size)) {
            $type = "{$type}({$this->size})";
        } elseif (in_array($type, ['varchar'])) {
            $type = "{$type}(255)";
        }
        $output = [
            "`{$this->name}`",
            $type
        ];
        if (isset($this->unsigned)) {
            $output []= 'UNSIGNED';
        }
        if (isset($this->default)) {
            $default = $this->default;
            if (in_array($this->type, ['varchar', 'text', 'char'])) {
                $default = "'{$default}'";
            }
            $output []= "DEFAULT {$default}";
        }
        if (isset($this->auto_increment)) {
            $output []= 'AUTO_INCREMENT';
        }
        if (isset($this->primary)) {
            $output []= 'PRIMARY KEY';
        }
        if (isset($this->foreign_table)) {
            $output []= "REFERENCES `{$this->foreign_table}` (`{$this->foreign_key}`)";
            $on = [
                'RESTRICT',
                'CASCADE',
                'SET_NULL',
                'NO_ACTION',
                'SET_DEFAULT'
            ];
            $output []= "ON DELETE {$on[$this->foreign_delete]}";
            $output []= "ON UPDATE {$on[$this->foreign_update]}";
        }
        return implode(' ', $output);
    }
}
