<?php

namespace RtmMail;

use Exception;

class Migration
{
    /**
     * OPTION_NAME - the name of the option saved in the "_options" table
     */
    const OPTION_NAME = "rtm_mail_migration_version";
    /**
     * version - current version of the plugin
     * @var string
     */
    private mixed $version;
    /**
     * notice_messages - Array of messages for displaying admin notices
     * @var array
     */
    private array $notice_messages;

    public function __construct($plugin_version = null)
    {
        // Set current plugin version
        $this->version = $plugin_version;
    }

    /**
     * check - Check if the migration version is different from the plugin version, if so check voor migration
     */
    public function check()
    {
        $migration_version = get_option(self::OPTION_NAME, '');
        if (empty($migration_version) || $this->version === null || version_compare($this->version, $migration_version, '>')) {
            // Get all the files in the Migrations folder
            $migration_files = array_diff(scandir(__DIR__ . '/Migrations/'), [ '..', '.' ]);
            // List of migration classes
            $migration_classes = [];

            // Loop through each file found in the directory
            foreach ($migration_files as $file) {
                // Remove the php extension
                $file = str_replace('.php', '', $file);
                // Check if the class exists, if so add it to the migration array
                if (class_exists("RtmMail\Migrations\\" . $file)) {
                    $migration_classes[] = "RtmMail\Migrations\\" . $file;
                }
            }

            // Empty current notice messages
            $this->notice_messages = [];
            // Create migrations array (this will contain all migration classes)
            $migrations = [];

            // Loop through all the migration classes
            foreach ($migration_classes as $migration_class) {
                // Check if the migration class implements the migration interface
                if (class_implements($migration_class, 'RtmMail\Migrations\MigrationInterface')) {
                    // Create new instance of the migration class and add it to the array
                    $migrations[] = new $migration_class();
                }
            }

            // Sort array by priority
            usort($migrations, function ($a, $b) {
                return ( $a->get_priority() < $b->get_priority() ) ? - 1 : 1;
            });

            // Boolean to check if the migration is successful
            $success = [];

            // Loop over the sorted migrations
            foreach ($migrations as $migration) {
                // Check if the migration class is already migrated, if not migrate
                if (! $migration->is_migrated()) {
                    $migration_class_name = get_class($migration);
                    try {
                        $migration->migrate();
                        $success[] = true;
                        Logger::info(
                            'Migration successful',
                            "Migration of class <code>{$migration_class_name}</code> was successful",
                            'Migration::check',
                            'Migrations',
                            []
                        );
                        do_action('rtmmail_migration_success', get_class($migration));
                        $this->notice_messages[] = [
                            'type' => 'success',
                            'text' => 'Migration of class <code>' . get_class($migration) . '</code> was successful'
                        ];
                    } catch (Exception $e) {
                        $success[] = false;
                        Logger::error(
                            'Migration failed',
                            "Migration of class <code>{$migration_class_name}</code> failed because of an error: {$e->getMessage()}",
                            'Migration::check',
                            'Migrations',
                            [
                                "exception:" => $e->getMessage(),
                            ]
                        );
                        $this->notice_messages[] = [
                            'type' => 'error',
                            'text' => 'Migration of class <code>' . get_class($migration) . '</code> failed due to an error - <code>' . $e->getMessage() . '</code>'
                        ];
                        break;
                    }
                }
            }
            // If there are any messages, output them
            if (! empty($this->notice_messages)) {
                add_action('admin_notices', [ $this, 'renderNotice' ]);
            }
            // Only update the version when everything went good
            if (! in_array(false, $success, true)) {
                $this->updateVersion();
            }
        }
    }

    /**
     * update_version - updates the migration version in the "_options" table
     */
    private function updateVersion(): void
    {
        update_option(self::OPTION_NAME, $this->version);
    }

    /**
     * render_notice - Renders admin notices saved in notice_messages
     */
    public function renderNotice(): void
    {
        foreach ($this->notice_messages as $message) {
            echo '<div class="notice notice-' . $message['type'] . ' is-dismissible">';
            echo '<p><strong>WP Mail Logger:</strong> ' . $message['text'] . '</p>';
            echo '</div>';
        }
    }
}
