<?php
namespace Core\Database;

use Core\Database\Operations\{
    CreateTable,
    RenameTable,
    AddColumn,
    RenameColumn,
    ModifyColumn,
    DropColumn,
    AddIndex,
    DropIndex,
    AddForeignKey,
    DropForeignKey
};
use Exception;

class SchemaOperator
{
    private static bool $method = true; // up = true, down = false
    private static bool $instance = false;

    public static function init($method = 'up'): void
    {
        if ($method === "down") {
            self::$method = false;
        }
        self::$instance = true;
    }

    private static function checkInit(): void
    {
        if (!self::$instance) {
            throw new Exception("No method found. Call SchemaOperator::init() first.");
        }
    }

    private static function execute($operation, string $type, array $params): void
    {
        self::checkInit();

        // Execute migration
        if (self::$method) {
            $operation->up();
        } else {
            $operation->down();
        }

        // Record migration history
        MigrationHistory::record([
            'operation' => $type,
            'params'    => $params,
            'direction' => self::$method ? 'up' : 'down',
        ]);
    }

    public static function createTable(string $table, array $columns): void
    {
        $op = new CreateTable($table, $columns);
        self::execute($op, 'CreateTable', ['table' => $table, 'columns' => $columns]);
    }

    public static function renameTable(string $old, string $new): void
    {
        $op = new RenameTable($old, $new);
        self::execute($op, 'RenameTable', ['old' => $old, 'new' => $new]);
    }

    public static function addColumn(string $table, string $column, string $type): void
    {
        $op = new AddColumn($table, $column, $type);
        self::execute($op, 'AddColumn', ['table' => $table, 'column' => $column, 'type' => $type]);
    }

    public static function renameColumn(string $table, string $old, string $new, string $type): void
    {
        $op = new RenameColumn($table, $old, $new, $type);
        self::execute($op, 'RenameColumn', compact('table', 'old', 'new', 'type'));
    }

    public static function modifyColumn(string $table, string $column, string $type): void
    {
        $op = new ModifyColumn($table, $column, $type);
        self::execute($op, 'ModifyColumn', compact('table', 'column', 'type'));
    }

    public static function dropColumn(string $table, string $column): void
    {
        $op = new DropColumn($table, $column);
        self::execute($op, 'DropColumn', compact('table', 'column'));
    }

    public static function addIndex(string $table, string $index, array $columns): void
    {
        $op = new AddIndex($table, $index, $columns);
        self::execute($op, 'AddIndex', compact('table', 'index', 'columns'));
    }

    public static function dropIndex(string $table, string $index): void
    {
        $op = new DropIndex($table, $index);
        self::execute($op, 'DropIndex', compact('table', 'index'));
    }

    public static function addForeignKey(string $table, string $column, string $refTable, string $refColumn, string $onDelete = 'CASCADE'): void
    {
        $op = new AddForeignKey($table, $column, $refTable, $refColumn, $onDelete);
        self::execute($op, 'AddForeignKey', compact('table', 'column', 'refTable', 'refColumn', 'onDelete'));
    }

    public static function dropForeignKey(string $table, string $key): void
    {
        $op = new DropForeignKey($table, $key);
        self::execute($op, 'DropForeignKey', compact('table', 'key'));
    }
}
