<?php

/**
 * Copyright © Resurs Bank AB. All rights reserved.
 * See LICENSE for license details.
 */

declare(strict_types=1);

namespace Resursbank\MerchantApi\Service;

use Db;
use Exception;
use Resursbank\MerchantApi\Config\Config;
use Resursbank\MerchantApi\Exception\InvalidDataException;
use Resursbank\MerchantApi\Util\Log;

/**
 * Custom migration system.
 */
class Migration
{
    public function __construct(
        private readonly Config $config
    ) {
    }

    /**
     * Execute SQL files which have not been executed yet.
     *
     * @return void
     * @throws InvalidDataException
     * @throws Exception
     */
    public function exec(): void
    {
        // 1. Pick up the last migration version from database.
        $lastMigrationVersion = $this->config->getMigrationVersion();

        // 2. Get a list of all migration files, skipping the ones that have already been executed.
        $migrations = $this->getMigrationList($lastMigrationVersion);

        // Execute each file one by one, after successful execution update the migration version in the database.
        foreach ($migrations as $version => $file) {
            $this->executeMigration($version, $file);
        }
    }

    /**
     * Execute SQL file.
     *
     * @param int $version
     * @param string $file
     * @return void
     * @throws InvalidDataException
     * @throws Exception
     */
    private function executeMigration(int $version, string $file): void
    {
        $sql = file_get_contents($file);

        if ($sql === false) {
            throw new InvalidDataException('Failed to read migration file: ' . $file);
        }

        // Replace [PREFIX] with the actual table prefix.
        $sql = str_replace('[PREFIX]', _DB_PREFIX_, $sql);

        // Execute SQL script.
        Db::getInstance()->execute($sql);

        // Mark new version in config table.
        $this->config->setMigrationVersion($version);
    }

    /**
     * Resolve list of all available SQL files.
     *
     * @param int $startingFrom
     * @return array
     */
    private function getMigrationList(int $startingFrom): array
    {
        $dir = _PS_MODULE_DIR_ . 'resursbank/migrations';

        // Find all SQL files inside the migrations directory named as "[version].sql" where [version] is a simple int.
        // Order the files by version number.
        $files = glob($dir . '/*.sql');
        $migrations = [];

        foreach ($files as $file) {
            $version = (int) pathinfo($file, PATHINFO_FILENAME);

            if ($version <= $startingFrom) {
                continue;
            }

            $migrations[$version] = $file;
        }

        return $migrations;
     }
}
