<?php

declare(strict_types=1);

namespace System\Migration;

use System\Contracts\DatabaseInterface;
use PDO;

final class MigrationRunner
{
    private PDO $pdo;

    public function __construct(
        DatabaseInterface $database
    ) {
        $this->pdo = $database->getConnection();
    }

    public function run(string $directory): void
    {
        $this->createMigrationTable();

        $batch = $this->nextBatch();

        $files = glob($directory . '/*.php');

        sort($files);

        foreach ($files as $file) {

            $name = basename($file);

            if ($this->alreadyExecuted($name)) {
                continue;
            }

            $callback = require $file;

            $sql = $callback();

try {

    $this->pdo->exec($sql);

} catch (\PDOException $e) {

    echo "<pre>";
    echo "Migration : {$name}\n\n";
    echo $sql;
    echo "\n\n";
    echo $e->getMessage();
    echo "</pre>";

    exit;
}

            $stmt = $this->pdo->prepare(
                "INSERT INTO migrations (migration,batch)
                 VALUES (?,?)"
            );

            $stmt->execute([$name,$batch]);

            echo "✔ {$name}<br>";
        }

        echo "<hr>Migration Complete";
    }

    private function alreadyExecuted(
        string $migration
    ): bool {

        $stmt = $this->pdo->prepare(

            "SELECT COUNT(*)
             FROM migrations
             WHERE migration=?"

        );

        $stmt->execute([$migration]);

        return (bool)$stmt->fetchColumn();
    }

    private function nextBatch(): int
    {
        return (int)$this->pdo
            ->query(
                "SELECT IFNULL(MAX(batch),0)+1
                 FROM migrations"
            )
            ->fetchColumn();
    }

    private function createMigrationTable(): void
    {
        $this->pdo->exec(
            "CREATE TABLE IF NOT EXISTS migrations
            (
                id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                migration VARCHAR(255) UNIQUE,
                batch INT,
                executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )"
        );
    }
}