<?php

// Ensure the file is not accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Plugin Updater System for BWDCV Plugin
 * Handles version upgrades and database updates
 *
 * @package BWDCV
 * @version 2.1.2
 */
class BWDCV_Updater {

    private $current_version;
    private $stored_version;
    private $update_lock_key = 'bwdcv_update_in_progress';

    public function __construct() {
        $this->current_version = BWDCV_VERSION;
        $this->stored_version  = get_option( 'bwdcv_version', '0.0.0' );

        // Hook into plugin activation and version check
        add_action( 'upgrader_process_complete', [ $this, 'on_plugin_update' ], 10, 2 );
        add_action( 'admin_init', [ $this, 'check_version_and_update' ] );
    }

    /**
     * Check if update is needed and run updater
     */
    public function check_version_and_update() {
        // Prevent multiple simultaneous updates
        if ( get_transient( $this->update_lock_key ) ) {
            return;
        }

        if ( version_compare( $this->current_version, $this->stored_version, '>' ) ) {
            $this->run_updater();
        }
    }

    /**
     * Hook for when plugins are updated via WordPress admin
     */
    public function on_plugin_update( $upgrader_object, $hook_extra ) {
        if ( ! isset( $hook_extra['plugins'] ) ) {
            return;
        }

        $our_plugin = plugin_basename( BWDCV_FILE );

        if ( in_array( $our_plugin, $hook_extra['plugins'] ) ) {
            // Force refresh stored version after plugin update
            $this->stored_version = get_option( 'bwdcv_version', '0.0.0' );
            $this->run_updater();
        }
    }

    /**
     * Main updater function - runs specific updates based on version
     */
    public function run_updater() {
        // Set update lock to prevent concurrent updates
        set_transient( $this->update_lock_key, true, 300 ); // 5 minute lock

        try {
            $updates_run = [];

            // Define version-specific updater classes
            $version_updates = [
                '2.1.2' => 'BWDCV_Updater_2_1_2',
                // Future versions can be added here:
                // '2.2.0' => 'Updater_2_2_0',
                // '3.0.0' => 'Updater_3_0_0',
            ];

            // Sort versions to ensure updates run in correct order
            uksort( $version_updates, 'version_compare' );

            // Run updates in order for versions between stored and current
            foreach ( $version_updates as $version => $updater_class ) {
                if ( $this->should_run_update( $version ) ) {
                    if ( ! class_exists( $updater_class ) ) {
                        // Try to include the updater file
                        $updater_file = plugin_dir_path( __FILE__ ) . "updates/{$updater_class}.php";
                        if ( file_exists( $updater_file ) ) {
                            require_once $updater_file;
                        } else {
                            throw new Exception( "Updater class {$updater_class} not found at {$updater_file}" );
                        }
                    }

                    $result = $this->run_version_update( $updater_class, $version );

                    if ( $result === false ) {
                        throw new Exception( "Update to version {$version} failed" );
                    }

                    $updates_run[] = $version;
                }
            }

            // Only update stored version after ALL updates succeed
            if ( ! empty( $updates_run ) ) {
                update_option( 'bwdcv_version', $this->current_version );

                // Set success notice if no specific notice was set by updaters
                if ( ! get_transient( 'bwdcv_update_notice' ) ) {
                    set_transient( 'bwdcv_update_notice', [
                        'type'    => 'success',
                        'message' => 'BWDCV Plugin updated successfully to version ' . $this->current_version
                    ], 30 );
                }
            }

        } catch ( Exception $e ) {
            error_log( 'BWDCV Plugin update failed: ' . $e->getMessage() );

            set_transient( 'bwdcv_update_notice', [
                'type'    => 'error',
                'message' => 'BWDCV Plugin update failed. Please check error logs or contact support.'
            ], 60 );
        }
        finally {
            // Always remove the update lock
            delete_transient( $this->update_lock_key );
        }
    }

    /**
     * Check if a specific version update should run
     *
     * @param  string  $version  Target version
     *
     * @return bool
     */
    private function should_run_update( $version ) {
        return version_compare( $this->stored_version, $version, '<' ) &&
               version_compare( $this->current_version, $version, '>=' );
    }

    /**
     * Run a specific version update
     *
     * @param  string  $updater_class  Class name
     * @param  string  $version  Version being updated to
     *
     * @return bool Success status
     */
    private function run_version_update( $updater_class, $version ) {
        try {
            $updater = new $updater_class( $this->stored_version, $this->current_version );

            // Check if the updater has a run method, otherwise assume constructor handles it
            if ( method_exists( $updater, 'run' ) ) {
                return $updater->run();
            }

            // If no explicit run method, assume constructor handled the update
            // and check for success via a status method
            if ( method_exists( $updater, 'was_successful' ) ) {
                return $updater->was_successful();
            }

            return true; // Assume success if no explicit status method

        } catch ( Exception $e ) {
            error_log( "Version {$version} update failed: " . $e->getMessage() );

            return false;
        }
    }

}

/**
 * Display admin notices
 */
function bwdcv_display_admin_notices() {
    $notice = get_transient( 'bwdcv_update_notice' );

    if ( $notice && current_user_can( 'manage_options' ) ) {
        $class = $notice['type'] === 'success' ? 'notice-success' : 'notice-error';

        printf(
            '<div class="notice %s is-dismissible"><p>%s</p></div>',
            esc_attr( $class ),
            esc_html( $notice['message'] )
        );

        delete_transient( 'bwdcv_update_notice' );
    }
}

/**
 * Initialize the updater system
 */
function bwdcv_init_updater() {
    new BWDCV_Updater();
}

// Initialize updater
add_action( 'plugins_loaded', 'bwdcv_init_updater' );

// Register admin notices
add_action( 'admin_notices', 'bwdcv_display_admin_notices' );
