<?php
error_reporting( E_ALL );
date_default_timezone_set( 'Europe/Warsaw' );

if ( PHP_SAPI !== 'cli' )
{
  header( 'Content-Type: text/plain; charset=utf-8' );
}

require_once __DIR__ . '/config.php';

function has_flag( $name )
{
  if ( PHP_SAPI === 'cli' )
  {
    global $argv;
    return in_array( '--' . $name, $argv, true );
  }

  return isset( $_GET[ $name ] ) && (string) $_GET[ $name ] === '1';
}

function statement_complete( $buffer, $delimiter )
{
  $trimmed = rtrim( $buffer );
  if ( $trimmed === '' )
  {
    return false;
  }

  $dl = strlen( $delimiter );
  if ( $dl === 0 )
  {
    return false;
  }

  return substr( $trimmed, -$dl ) === $delimiter;
}

function strip_statement_delimiter( $buffer, $delimiter )
{
  $trimmed = rtrim( $buffer );
  $dl = strlen( $delimiter );

  if ( $dl > 0 && substr( $trimmed, -$dl ) === $delimiter )
  {
    return rtrim( substr( $trimmed, 0, -$dl ) );
  }

  return $trimmed;
}

function execute_sql_file( PDO $pdo, $file_path )
{
  $handle = fopen( $file_path, 'r' );
  if ( !$handle )
  {
    throw new RuntimeException( 'Nie mozna otworzyc pliku: ' . $file_path );
  }

  $delimiter = ';';
  $buffer = '';

  while ( ( $line = fgets( $handle ) ) !== false )
  {
    if ( preg_match( '/^\s*DELIMITER\s+(\S+)\s*$/i', $line, $m ) )
    {
      $delimiter = $m[1];
      continue;
    }

    $trim = trim( $line );
    if ( $trim !== '' && preg_match( '/^\s*(--|#)/', $trim ) )
    {
      continue;
    }

    $buffer .= $line;

    if ( statement_complete( $buffer, $delimiter ) )
    {
      $statement = strip_statement_delimiter( $buffer, $delimiter );
      $statement = trim( $statement );

      if ( $statement !== '' )
      {
        $pdo -> exec( $statement );
      }

      $buffer = '';
    }
  }

  fclose( $handle );

  $tail = trim( $buffer );
  if ( $tail !== '' )
  {
    $pdo -> exec( $tail );
  }
}

try
{
  $dsn = 'mysql:host=' . $database['host'] . ';dbname=' . $database['name'] . ';charset=utf8';
  $pdo = new PDO( $dsn, $database['user'], $database['password'], [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
  ] );

  $pdo -> exec(
    'CREATE TABLE IF NOT EXISTS `schema_migrations` (
      `id` INT(11) NOT NULL AUTO_INCREMENT,
      `filename` VARCHAR(255) NOT NULL,
      `applied_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_schema_migrations_filename` (`filename`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8'
  );

  $include_demo = has_flag( 'with_demo' );
  $force = has_flag( 'force' );

  $files = glob( __DIR__ . '/migrations/*.sql' );
  sort( $files, SORT_NATURAL | SORT_FLAG_CASE );

  $selected = [];
  foreach ( $files as $file_path )
  {
    $filename = basename( $file_path );

    if ( preg_match( '/^\d+_.+\.sql$/', $filename ) )
    {
      $selected[] = $file_path;
      continue;
    }

    if ( $include_demo && $filename === 'demo_data.sql' )
    {
      $selected[] = $file_path;
    }
  }

  if ( empty( $selected ) )
  {
    echo "Brak migracji do uruchomienia.\n";
    exit;
  }

  echo "Uruchamianie migracji...\n";
  echo 'Tryb force: ' . ( $force ? 'TAK' : 'NIE' ) . "\n";
  echo 'Demo data: ' . ( $include_demo ? 'TAK' : 'NIE' ) . "\n\n";

  $applied_count = 0;
  $skipped_count = 0;

  foreach ( $selected as $file_path )
  {
    $filename = basename( $file_path );

    $stmt = $pdo -> prepare( 'SELECT COUNT(1) FROM schema_migrations WHERE filename = :filename' );
    $stmt -> execute( [ ':filename' => $filename ] );
    $already_applied = (int) $stmt -> fetchColumn() > 0;

    if ( $already_applied && !$force )
    {
      echo '[SKIP] ' . $filename . " (juz zastosowana)\n";
      $skipped_count++;
      continue;
    }

    execute_sql_file( $pdo, $file_path );

    $stmt = $pdo -> prepare(
      'INSERT INTO schema_migrations (filename, applied_at)
       VALUES (:filename, NOW())
       ON DUPLICATE KEY UPDATE applied_at = NOW()'
    );
    $stmt -> execute( [ ':filename' => $filename ] );

    echo '[OK]   ' . $filename . "\n";
    $applied_count++;
  }

  echo "\nZakonczono.\n";
  echo 'Zastosowano: ' . $applied_count . "\n";
  echo 'Pominieto:   ' . $skipped_count . "\n";
}
catch ( Throwable $e )
{
  http_response_code( 500 );
  echo '[BLAD] ' . $e -> getMessage() . "\n";
  exit( 1 );
}
