<?php
namespace nur\sery\db\sqlite;

use nur\sery\php\nur_func;

class _migration {
  static function with($migrations): self {
    if ($migrations instanceof static) {
      return $migrations;
    } elseif ($migrations instanceof self) {
      return new static($migrations->migrations);
    } else {
      return new static($migrations);
    }
  }

  const MIGRATE = null;

  function __construct($migrations) {
    if ($migrations === null) $migrations = static::MIGRATE;
    if ($migrations === null) $migrations = [];
    elseif (is_string($migrations)) $migrations = [$migrations];
    elseif (is_callable($migrations)) $migrations = [$migrations];
    elseif (!is_array($migrations)) $migrations = [strval($migrations)];
    $this->migrations = $migrations;
  }

  /** @var callable[]|string[]  */
  protected $migrations;
  
  function migrate(Sqlite $sqlite): void {
    $sqlite->exec("create table if not exists _migration(key varchar primary key, value varchar not null, done integer default 0)");
    foreach ($this->migrations as $key => $migration) {
      $exists = $sqlite->get("select 1 from _migration where key = :key and done = 1", [
        "key" => $key,
      ]);
      if (!$exists) {
        $sqlite->exec("insert or replace into _migration(key, value, done) values(:key, :value, :done)", [
          "key" => $key,
          "value" => $migration,
          "done" => 0,
        ]);
        if (is_string($migration) && !nur_func::is_method($migration)) {
          $sqlite->exec($migration);
        } else {
          nur_func::ensure_func($migration, $this, $args);
          nur_func::call($migration, $sqlite, $key, ...$args);
        }
        $sqlite->exec("update _migration set done = 1 where key = :key", [
          "key" => $key,
        ]);
      }
    }
  }
}
