<?php

namespace apexl\Io\modules\migration\controllers;
use apexl\Config\Singleton;
use apexl\hashing\Hash;
use apexl\Io\includes\System;
use apexl\Io\modules\install\services\databaseTools;
use apexl\Io\modules\install\services\Install;
use apexl\Io\services\pathUtility;

use apexl\Vault\Vault;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

class migrationController {

    /** @var Vault  */
    protected $database;

    public function __construct(Vault $database)
    {
        $this->database = $database;
    }

    /**
     * Migrate the database according to the files located in migrationDirectories
     * @param Request $request
     * @param Response $response
     * @method GET
     * @return Response
     */
    public function migrate(Request $request, Response $response)
    {
        $migrationDirectories = [
            $_SERVER['DOCUMENT_ROOT'].'/../migration/'
        ];
        $migrationsProcessed = [];
        $migrations = $this->database->select('migrations')->fields()->execute()->fetchAll();
        $previousMigrations = [];
        foreach ($migrations as $migration) {
            $previousMigrations[$migration->version] = 1;
        }

        $migrationsToRun = [];
        foreach ($migrationDirectories as $migrationDirectory) {
            if (file_exists($migrationDirectory)) {
                $cdir = scandir($migrationDirectory);
                foreach ($cdir as $key => $value) {
                    if (!in_array($value, [".", ".."])){
                        if (!preg_match('/^version\_[0-9]{14,14}\.sql$/', $value)) {
                            echo "Error: Incorrect file name $value.\nAll migration file names must follow the format version_yyyymmddhhmmss.sql." ;
                            exit();
                        } elseif (!isset($previousMigrations[$value])) {
                            $migrationsToRun[] = (object)[
                                'dir' => $migrationDirectory,
                                'filename' => $value
                            ];
                            $previousMigrations[$value] = 1;
                        }
                    }
                }
            }
        }

        usort($migrationsToRun, [$this, "cmpMigrationFilenames"]); // Sort by filename to run earliest migrations first

        foreach ($migrationsToRun as $migration) {
            if ($this->migrateFile($migration->dir, $migration->filename)) {
                $migrationsProcessed[] = $migration->filename;
            }
        }

        $data = [
            'migrationsProcessed' => $migrationsProcessed
        ];
        return System::asJson($response, $data);
    }

    protected function cmpMigrationFilenames($a, $b) {
        return strcmp($a->filename, $b->filename);
    }

    /**
     * Migrate a single SQL file
     * @param $migrationDir
     * @param $fileName
     * @return bool|void
     */
    protected function migrateFile($migrationDir, $fileName)
    {
        $sql = file_get_contents($migrationDir.$fileName);
        list($result, $error) = $this->database->executeRaw($sql);
        if (!$result) {
            echo "Failed to execute: $filePath:\n$error";
            exit();
        } else {
            $this->database->insert('migrations')->fields(['version' => $fileName])->execute();
            return true;
        }

        return false; // Should never get to this line of code
    }
}