<?php
/**
 * Migration Runner
 * Automatically detects and runs database migrations
 */

// Find db_config.php from current directory
$dbConfigPath = __DIR__ . '/../../db_config.php';
if (!file_exists($dbConfigPath)) {
    // Try alternative path
    $dbConfigPath = __DIR__ . '/../db_config.php';
}
if (!file_exists($dbConfigPath)) {
    // Try from current working directory
    $dbConfigPath = 'db_config.php';
}
require_once $dbConfigPath;

class MigrationRunner {
    private $pdo;
    private $migrationsPath;
    
    public function __construct($migrationsPath = null) {
        $this->pdo = getDBConnection();
        $this->migrationsPath = $migrationsPath ?: __DIR__;
    }
    
    /**
     * Run all pending migrations
     */
    public function runMigrations() {
        $this->createMigrationsTable();
        
        $migrations = $this->getPendingMigrations();
        
        if (empty($migrations)) {
            echo "No pending migrations found.\n";
            return true;
        }
        
        echo "Found " . count($migrations) . " pending migration(s).\n\n";
        
        $success = true;
        foreach ($migrations as $migration) {
            echo "Running migration: {$migration['name']}\n";
            
            if ($this->runMigration($migration)) {
                echo "✓ Migration {$migration['name']} completed successfully\n\n";
            } else {
                echo "✗ Migration {$migration['name']} failed\n\n";
                $success = false;
                break;
            }
        }
        
        return $success;
    }
    
    /**
     * Run a specific migration by name
     */
    public function runMigrationByName($migrationName) {
        $this->createMigrationsTable();
        
        $migrations = $this->getMigrationFiles();
        $targetMigration = null;
        
        foreach ($migrations as $migration) {
            if ($migration['name'] === $migrationName) {
                $targetMigration = $migration;
                break;
            }
        }
        
        if (!$targetMigration) {
            echo "Migration {$migrationName} not found.\n";
            return false;
        }
        
        echo "Running migration: {$targetMigration['name']}\n";
        
        if ($this->runMigration($targetMigration)) {
            echo "✓ Migration {$targetMigration['name']} completed successfully\n";
            return true;
        } else {
            echo "✗ Migration {$targetMigration['name']} failed\n";
            return false;
        }
    }
    
    /**
     * Get all migration files
     */
    private function getMigrationFiles() {
        $files = glob($this->migrationsPath . '/*_migration.php');
        $migrations = [];
        
        foreach ($files as $file) {
            $filename = basename($file);
            $name = str_replace('_migration.php', '', $filename);
            $migrations[] = [
                'name' => $name,
                'file' => $file,
                'class' => $this->getMigrationClassName($name)
            ];
        }
        
        // Sort by filename (which should include timestamp)
        usort($migrations, function($a, $b) {
            return strcmp($a['name'], $b['name']);
        });
        
        return $migrations;
    }
    
    /**
     * Get pending migrations
     */
    private function getPendingMigrations() {
        $allMigrations = $this->getMigrationFiles();
        $appliedMigrations = $this->getAppliedMigrations();
        
        $pending = [];
        foreach ($allMigrations as $migration) {
            if (!in_array($migration['name'], $appliedMigrations)) {
                $pending[] = $migration;
            }
        }
        
        return $pending;
    }
    
    /**
     * Get applied migrations
     */
    private function getAppliedMigrations() {
        $stmt = $this->pdo->query("SELECT migration_name FROM migrations ORDER BY applied_at");
        return $stmt->fetchAll(PDO::FETCH_COLUMN);
    }
    
    /**
     * Run a single migration
     */
    private function runMigration($migration) {
        try {
            // Handle both array and object formats
            if (is_array($migration)) {
                require_once $migration['file'];
                $className = $migration['class'];
                $migrationName = $migration['name'];
            } else {
                // It's already an instance
                $className = get_class($migration);
                $migrationName = $className;
            }
            
            if (is_array($migration)) {
                if (!class_exists($className)) {
                    throw new Exception("Migration class {$className} not found");
                }
                
                $migrationInstance = new $className();
            } else {
                $migrationInstance = $migration;
            }
            
            if (!method_exists($migrationInstance, 'up')) {
                throw new Exception("Migration class {$className} missing 'up' method");
            }
            
            return $migrationInstance->up();
            
        } catch (Exception $e) {
            $migrationName = is_array($migration) ? $migration['name'] : get_class($migration);
            echo "Error running migration {$migrationName}: " . $e->getMessage() . "\n";
            return false;
        }
    }
    
    /**
     * Get migration class name from filename
     */
    private function getMigrationClassName($migrationName) {
        $parts = explode('_', $migrationName);
        $className = '';
        
        foreach ($parts as $part) {
            $className .= ucfirst($part);
        }
        
        return $className . 'Migration';
    }
    
    /**
     * Create migrations table
     */
    private function createMigrationsTable() {
        $sql = "
        CREATE TABLE IF NOT EXISTS migrations (
            id INT AUTO_INCREMENT PRIMARY KEY,
            migration_name VARCHAR(255) NOT NULL,
            version VARCHAR(50) NOT NULL,
            applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            UNIQUE KEY unique_migration (migration_name, version)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
        ";
        
        $this->pdo->exec($sql);
    }
    
    /**
     * Check if specific feature tables exist
     */
    public function checkFeatureTables($featureName) {
        $featureTables = $this->getFeatureTables($featureName);
        $existing = [];
        $missing = [];
        
        foreach ($featureTables as $table) {
            $stmt = $this->pdo->query("SHOW TABLES LIKE '$table'");
            if ($stmt->rowCount() > 0) {
                $existing[] = $table;
            } else {
                $missing[] = $table;
            }
        }
        
        return [
            'existing' => $existing,
            'missing' => $missing,
            'all_exist' => empty($missing)
        ];
    }
    
    /**
     * Get tables required for a feature
     */
    private function getFeatureTables($featureName) {
        $featureTables = [
            'special_access_links' => ['special_access_links'],
            'all' => ['special_access_links', 'migrations']
        ];
        
        return $featureTables[$featureName] ?? [];
    }
    
    /**
     * Auto-migrate feature if tables don't exist
     */
    public function autoMigrateFeature($featureName) {
        $tables = $this->checkFeatureTables($featureName);
        
        if ($tables['all_exist']) {
            echo "All required tables for {$featureName} already exist.\n";
            return true;
        }
        
        echo "Missing tables for {$featureName}: " . implode(', ', $tables['missing']) . "\n";
        echo "Running migrations...\n";
        
        return $this->runMigrations();
    }
}

// CLI execution
if (php_sapi_name() === 'cli') {
    $runner = new MigrationRunner();
    
    $command = $argv[1] ?? 'run';
    $feature = $argv[2] ?? null;
    
    switch ($command) {
        case 'run':
            $runner->runMigrations();
            break;
        case 'check':
            if ($feature) {
                $tables = $runner->checkFeatureTables($feature);
                echo "Feature: {$feature}\n";
                echo "Existing tables: " . implode(', ', $tables['existing']) . "\n";
                echo "Missing tables: " . implode(', ', $tables['missing']) . "\n";
                echo "All exist: " . ($tables['all_exist'] ? 'Yes' : 'No') . "\n";
            } else {
                echo "Usage: php migration_runner.php check <feature_name>\n";
            }
            break;
        case 'auto':
            if ($feature) {
                $runner->autoMigrateFeature($feature);
            } else {
                echo "Usage: php migration_runner.php auto <feature_name>\n";
            }
            break;
        default:
            echo "Usage: php migration_runner.php [run|check|auto] [feature_name]\n";
    }
}
?>
