<?php
declare(strict_types=1);

namespace Celena\Core\Database;

use Closure;

/**
 * Декларативные миграции. Поддерживает обе СУБД через Blueprint::toSql().
 */
final class Schema
{
    public function __construct(private readonly Connection $conn)
    {
    }

    public function create(string $table, Closure $callback): void
    {
        $bp = new Blueprint($this->conn->table($table));
        $callback($bp);
        foreach ($bp->toSql($this->conn->driver()) as $sql) {
            $this->conn->exec($sql);
        }
    }

    public function dropIfExists(string $table): void
    {
        $this->conn->exec('DROP TABLE IF EXISTS ' . $this->conn->table_q($table));
    }

    public function hasTable(string $table): bool
    {
        $name = $this->conn->table($table);
        $driver = $this->conn->driver()->name();
        if ($driver === 'pgsql') {
            // current_schema() — иначе видим одноимённые таблицы чужих схем кластера.
            $row = $this->conn->run(
                "SELECT 1 FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = ? LIMIT 1",
                [$name]
            )->fetch();
        } else {
            $row = $this->conn->run(
                "SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ? LIMIT 1",
                [$name]
            )->fetch();
        }
        return $row !== false && $row !== null;
    }

    /**
     * Есть ли колонка в таблице. Кросс-СУБД: information_schema с фильтром по текущей
     * базе/схеме (SHOW COLUMNS … LIKE ? в MySQL не работает — SHOW не принимает плейсхолдеры).
     */
    public function hasColumn(string $table, string $column): bool
    {
        $name = $this->conn->table($table);
        $driver = $this->conn->driver()->name();
        if ($driver === 'pgsql') {
            $row = $this->conn->run(
                "SELECT 1 FROM information_schema.columns WHERE table_schema = current_schema() AND table_name = ? AND column_name = ? LIMIT 1",
                [$name, $column]
            )->fetch();
        } else {
            $row = $this->conn->run(
                "SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ? LIMIT 1",
                [$name, $column]
            )->fetch();
        }
        return $row !== false && $row !== null;
    }
}
