<?php

session_start();

//===
// Bound to the current request
// Prevents other sessions from being started "by accident"
$fileName = 'installing.php';
$ip = $_SERVER[ 'REMOTE_ADDR' ];

if ( !is_file( $fileName ) ) {
    file_put_contents( $fileName, '<?php $ip="' . $ip . '";' );
}
if ( file_get_contents( $fileName ) !== '<?php $ip="' . $ip . '";' ) {
    exit( 'Session already started' );
}
//====

$requirementsFile = __DIR__ . '/requirements.json';
$requirements = json_decode( file_get_contents( $requirementsFile ), true );

$step = isset( $_GET[ 'step' ] ) ? (int)$_GET[ 'step' ] : 0;

function isShellCommandAvailable( string $cmd ): bool
{
    if ( $cmd === 'php' ) {
        return true;
    }

    if ( !function_exists( 'proc_open' ) ) {
        return false;
    }

    $checkCmd = ( PHP_OS_FAMILY === 'Windows' ) ? 'where ' . escapeshellarg( $cmd ) : 'command -v ' . escapeshellarg( $cmd );
    $descriptors = [
        0 => [ 'pipe', 'r' ],
        1 => [ 'pipe', 'w' ],
        2 => [ 'pipe', 'w' ],
    ];

    $process = @proc_open( $checkCmd, $descriptors, $pipes );
    if ( !is_resource( $process ) ) {
        return false;
    }

    fclose( $pipes[ 0 ] );
    fclose( $pipes[ 1 ] );
    fclose( $pipes[ 2 ] );

    return proc_close( $process ) === 0;
}

function runArtisanInstall( string $parentDir, array $siteDetails ): array
{
    $autoload = $parentDir . '/vendor/autoload.php';
    if ( !is_file( $autoload ) ) {
        return [
            'success' => false,
            'message' => 'vendor/autoload.php not found. The archive seems incomplete.',
        ];
    }

    $bootstrap = $parentDir . '/bootstrap/app.php';
    if ( !is_file( $bootstrap ) ) {
        return [
            'success' => false,
            'message' => 'Laravel bootstrap not found.',
        ];
    }

    $previousCwd = getcwd();
    chdir( $parentDir );

    try {
        if ( !defined( 'LARAVEL_START' ) ) {
            define( 'LARAVEL_START', microtime( true ) );
        }

        require $autoload;

        $app = require $bootstrap;

        $input = new Symfony\Component\Console\Input\ArrayInput( [
            'command' => 'app:install',
            '--name' => $siteDetails[ 'site_name' ] ?? 'My ValPress Site',
            '--username' => $siteDetails[ 'admin_user' ] ?? 'admin',
            '--password' => $siteDetails[ 'admin_pass' ] ?? '',
            '--email' => $siteDetails[ 'admin_email' ] ?? '',
        ] );
        $input->setInteractive( false );

        $status = $app->handleCommand( $input );

        if ( $status === 0 ) {
            return [ 'success' => true ];
        }

        return [
            'success' => false,
            'message' => 'Installation command failed with exit code ' . $status,
        ];
    }
    catch ( Throwable $e ) {
        return [
            'success' => false,
            'message' => 'Installation failed: ' . $e->getMessage(),
        ];
    }
    finally {
        if ( $previousCwd !== false ) {
            chdir( $previousCwd );
        }
    }
}

function isDirectoryWritable( string $path ): bool
{
    if ( is_dir( $path ) ) {
        return is_writable( $path );
    }

    if ( file_exists( $path ) ) {
        return false;
    }

    $parent = dirname( $path );
    if ( $parent === $path ) {
        return false;
    }

    return isDirectoryWritable( $parent );
}

function checkWritableDirectories( array $requirements, string $baseDir ): array
{
    $results = [
        'compatible' => true,
        'details' => [],
    ];

    foreach ( $requirements[ 'writable_directories' ] as $dir ) {
        $path = $baseDir . DIRECTORY_SEPARATOR . str_replace( '/', DIRECTORY_SEPARATOR, $dir );
        $writable = isDirectoryWritable( $path );
        $detailKey = 'writable_' . str_replace( [ '/', '\\', '.' ], '_', $dir );

        if ( is_dir( $path ) ) {
            $current = is_writable( $path ) ? 'Yes' : 'No';
        }
        elseif ( !file_exists( $path ) ) {
            $current = 'Missing';
        }
        else {
            $current = 'Not a directory';
        }

        $results[ 'details' ][ $detailKey ] = [
            'name' => 'Writable: ' . $dir,
            'required' => 'Writable',
            'current' => $current,
            'status' => $writable,
        ];

        if ( !$writable ) {
            $results[ 'compatible' ] = false;
        }
    }

    return $results;
}

function checkRequirements( $requirements ): array
{
    $results = [
        'compatible' => true,
        'details' => [],
    ];

    // PHP Version
    $phpRequired = $requirements[ 'php' ] ?? '8.2.0';
    $phpCompatible = version_compare( PHP_VERSION, str_replace( '>=', '', $phpRequired ), '>=' );
    $results[ 'details' ][ 'php' ] = [
        'name' => 'PHP Version',
        'required' => $phpRequired,
        'current' => PHP_VERSION,
        'status' => $phpCompatible,
    ];
    if ( !$phpCompatible ) {
        $results[ 'compatible' ] = false;
    }

    // Extensions
    $databaseExtensions = [ 'pdo_mysql', 'pdo_pgsql', 'pdo_sqlite', 'pdo_sqlsrv' ];
    $hasAtLeastOneDbDriver = false;

    foreach ( $requirements[ 'extensions' ] as $ext ) {
        if ( $ext === 'intl' ) {
            $status = extension_loaded( 'intl' );
            $results[ 'details' ][ 'extension_intl' ] = [
                'name' => 'Extension: intl',
                'required' => 'Installed',
                'current' => $status ? 'Yes' : 'No',
                'status' => $status,
            ];
            if ( !$status ) {
                $results[ 'compatible' ] = false;
            }
            continue;
        }

        $status = extension_loaded( $ext );
        $results[ 'details' ][ 'extension_' . $ext ] = [
            'name' => 'Extension: ' . $ext,
            'required' => 'Installed',
            'current' => $status ? 'Yes' : 'No',
            'status' => $status,
        ];
        if ( !$status ) {
            $results[ 'compatible' ] = false;
        }
    }

    // Check database extensions separately
    foreach ( $databaseExtensions as $ext ) {
        $status = extension_loaded( $ext );
        if ( $status ) {
            $hasAtLeastOneDbDriver = true;
        }
        $results[ 'details' ][ 'extension_' . $ext ] = [
            'name' => 'Extension: ' . $ext,
            'required' => 'Optional',
            'current' => $status ? 'Yes' : 'No',
            'status' => true, // Don't block if a single driver is missing
        ];
    }

    if ( !$hasAtLeastOneDbDriver ) {
        $results[ 'compatible' ] = false;
        // Add a general error for missing DB drivers
        $results[ 'details' ][ 'db_drivers' ] = [
            'name' => 'Database Drivers',
            'required' => 'At least one driver (PDO)',
            'current' => 'None',
            'status' => false,
        ];
    }

    // Disk Space
    $diskRequiredMb = $requirements[ 'disk_space_mb' ] ?? 150;
    $freeSpace = disk_free_space( __DIR__ ) / ( 1024 * 1024 );
    $diskCompatible = $freeSpace >= $diskRequiredMb;
    $results[ 'details' ][ 'disk_space' ] = [
        'name' => 'Disk Space',
        'required' => $diskRequiredMb . ' MB',
        'current' => round( $freeSpace, 2 ) . ' MB',
        'status' => $diskCompatible,
    ];
    if ( !$diskCompatible ) {
        $results[ 'compatible' ] = false;
    }

    // Writable Directories
    $parentDir = dirname( __DIR__ );
    $hasExtractedApp = is_file( $parentDir . '/artisan' ) || is_dir( $parentDir . '/vendor' );

    if ( $hasExtractedApp ) {
        $writableResults = checkWritableDirectories( $requirements, $parentDir );
        $results[ 'details' ] = array_merge( $results[ 'details' ], $writableResults[ 'details' ] );
        if ( !$writableResults[ 'compatible' ] ) {
            $results[ 'compatible' ] = false;
        }
    }
    else {
        // Pre-extraction: the archive has not been unpacked yet, so only verify
        // that the installation root is writable enough to extract files there.
        $rootWritable = is_writable( $parentDir );
        $results[ 'details' ][ 'root_writable' ] = [
            'name' => 'Root Directory Writable',
            'required' => 'Writable',
            'current' => $rootWritable ? 'Yes' : 'No',
            'status' => $rootWritable,
        ];
        if ( !$rootWritable ) {
            $results[ 'compatible' ] = false;
        }
    }

    // Shell Commands (php runs in-process; other commands use proc_open when available)
    foreach ( $requirements[ 'shell_commands' ] as $cmd ) {
        $status = isShellCommandAvailable( $cmd );
        $results[ 'details' ][ 'shell_' . $cmd ] = [
            'name' => 'Command: ' . $cmd,
            'required' => 'Available',
            'current' => $status ? 'Yes' : 'No',
            'status' => $status,
        ];
        if ( !$status ) {
            $results[ 'compatible' ] = false;
        }
    }

    return $results;
}

if ( $_SERVER[ 'REQUEST_METHOD' ] === 'POST' ) {
    $action = $_POST[ 'action' ] ?? '';

    if ( $action === 'test_db' ) {
        $connection = $_POST[ 'db_connection' ] ?? 'mysql';
        $host = $_POST[ 'db_host' ] ?? '';
        $port = $_POST[ 'db_port' ] ?? '';
        $name = $_POST[ 'db_name' ] ?? '';
        $user = $_POST[ 'db_user' ] ?? '';
        $pass = $_POST[ 'db_pass' ] ?? '';

        try {
            // Check if the required extension for the selected driver is installed
            $driverExtensions = [
                'mysql' => 'pdo_mysql',
                'mariadb' => 'pdo_mysql',
                'pgsql' => 'pdo_pgsql',
                'sqlite' => 'pdo_sqlite',
                'sqlsrv' => 'pdo_sqlsrv',
            ];

            if ( isset( $driverExtensions[ $connection ] ) ) {
                $ext = $driverExtensions[ $connection ];
                if ( !extension_loaded( $ext ) ) {
                    echo json_encode( [ 'success' => false, 'message' => "PHP extension '$ext' is required for the $connection driver but is not installed." ] );
                    exit;
                }
            }

            if ( $connection === 'sqlite' ) {
                $dsn = "sqlite:$name";
                $pdo = new PDO( $dsn );
            }
            elseif ( $connection === 'sqlsrv' ) {
                $dsn = "sqlsrv:Server=$host,$port;Database=$name";
                $pdo = new PDO( $dsn, $user, $pass );
            }
            else {
                $dsn = "$connection:host=$host;port=$port;dbname=$name;charset=utf8mb4";
                $options = [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false,
                ];
                $pdo = new PDO( $dsn, $user, $pass, $options );
            }

            $_SESSION[ 'db_config' ] = [
                'connection' => $connection,
                'host' => $host,
                'port' => $port,
                'name' => $name,
                'user' => $user,
                'pass' => $pass,
                'url' => $_POST[ 'site_url' ] ?? '',
            ];
            echo json_encode( [ 'success' => true ] );
        }
        catch ( PDOException $e ) {
            echo json_encode( [ 'success' => false, 'message' => $e->getMessage() ] );
        }
        exit;
    }

    if ( $action === 'extract' ) {
        set_time_limit( 600 );

        $extractTo = dirname( __DIR__ );
        $zipFile = __DIR__ . '/valpress.zip';

        if ( !file_exists( $zipFile ) ) {
            echo json_encode( [ 'success' => false, 'message' => 'Installer archive (valpress.zip) missing.' ] );
            exit;
        }

        if ( !class_exists( 'ZipArchive' ) ) {
            echo json_encode( [ 'success' => false, 'message' => 'ZipArchive extension not found.' ] );
            exit;
        }

        $zip = new ZipArchive;
        $res = $zip->open( $zipFile );
        if ( $res === true ) {
            if ( $zip->extractTo( $extractTo ) ) {
                $zip->close();

                $writableResults = checkWritableDirectories( $requirements, $extractTo );
                if ( !$writableResults[ 'compatible' ] ) {
                    $failedDirs = [];
                    foreach ( $writableResults[ 'details' ] as $detail ) {
                        if ( !$detail[ 'status' ] ) {
                            $failedDirs[] = $detail[ 'name' ];
                        }
                    }

                    echo json_encode( [
                        'success' => false,
                        'message' => 'Archive extracted, but required directories are not writable: ' . implode( ', ', $failedDirs ) . '. Please fix permissions and try again.',
                    ] );
                    exit;
                }

                echo json_encode( [ 'success' => true ] );
            }
            else {
                echo json_encode( [ 'success' => false, 'message' => 'Failed to extract archive. Check permissions.' ] );
            }
        }
        else {
            $errorMsg = 'Failed to open zip archive. Error code: ' . $res;
            echo json_encode( [ 'success' => false, 'message' => $errorMsg ] );
        }
        exit;
    }

    if ( $action === 'setup_env' ) {
        $dbConfig = $_SESSION[ 'db_config' ] ?? [];
        if ( empty( $dbConfig ) ) {
            echo json_encode( [ 'success' => false, 'message' => 'Database configuration missing in session.' ] );
            exit;
        }

        $parentDir = dirname( __DIR__ );
        $exampleEnv = $parentDir . '/.env.example';
        $envFile = $parentDir . '/.env';

        if ( file_exists( $exampleEnv ) ) {
            copy( $exampleEnv, $envFile );
        }
        else {
            // Create a basic one if missing
            $content = "APP_NAME=ValPress\n" .
                "APP_ENV=local\n" .
                "APP_KEY=\n" .
                "APP_DEBUG=true\n" .
                "APP_URL=\n" .
                "DB_CONNECTION=mysql\n" .
                "DB_HOST=127.0.0.1\n" .
                "DB_PORT=3306\n" .
                "DB_DATABASE=\n" .
                "DB_USERNAME=\n" .
                "DB_PASSWORD=\n";
            file_put_contents( $envFile, $content );
        }

        $content = file_get_contents( $envFile );
        $replacements = [
            'APP_URL' => $dbConfig[ 'url' ],
            'DB_CONNECTION' => $dbConfig[ 'connection' ],
            'DB_HOST' => $dbConfig[ 'host' ],
            'DB_PORT' => $dbConfig[ 'port' ],
            'DB_DATABASE' => $dbConfig[ 'name' ],
            'DB_USERNAME' => $dbConfig[ 'user' ],
            'DB_PASSWORD' => $dbConfig[ 'pass' ],
        ];

        foreach ( $replacements as $key => $value ) {
            if ( preg_match( "/^#?\s*{$key}=.*/m", $content ) ) {
                $content = preg_replace( "/^#?\s*{$key}=.*/m", "{$key}={$value}", $content );
            }
            else {
                $content .= "\n{$key}={$value}";
            }
        }

        if ( file_put_contents( $envFile, $content ) ) {
            // Create a root index.php that redirects to public/ for environments not pointed to public/
            $rootIndex = $parentDir . '/index.php';
            if ( !file_exists( $rootIndex ) ) {
                $rootIndexContent = "<?php\n\n/**\n * ValPress CMS - Root Redirector\n * This file redirects requests to the public directory for environments\n * where the web server is not pointed to the public folder.\n */\n\nif ( strpos( \$_SERVER['REQUEST_URI'], '/installer/' ) !== false ) {\n    // Allow installer to work\n    return false;\n}\n\nif ( file_exists( __DIR__ . '/public/index.php' ) ) {\n    require_once __DIR__ . '/public/index.php';\n} else {\n    echo 'ValPress public/index.php not found. Please check your installation.';\n}\n";
                file_put_contents( $rootIndex, $rootIndexContent );
            }

            // Create a root .htaccess that rewrites everything to public/
            $rootHtaccess = $parentDir . '/.htaccess';
            if ( !file_exists( $rootHtaccess ) ) {
                $rootHtaccessContent = "<IfModule mod_rewrite.c>\n    RewriteEngine On\n    RewriteCond %{REQUEST_URI} !^/public/\n    RewriteCond %{REQUEST_URI} !^/installer/\n    RewriteRule ^(.*)$ public/$1 [L]\n</IfModule>\n";
                file_put_contents( $rootHtaccess, $rootHtaccessContent );
            }

            echo json_encode( [ 'success' => true ] );
        }
        else {
            echo json_encode( [ 'success' => false, 'message' => 'Failed to create .env file.' ] );
        }
        exit;
    }

    if ( $action === 'install' ) {
        $_SESSION[ 'site_details' ] = [
            'site_name' => $_POST[ 'site_name' ] ?? 'My ValPress Site',
            'admin_user' => $_POST[ 'admin_user' ] ?? 'admin',
            'admin_pass' => $_POST[ 'admin_pass' ] ?? '',
            'admin_email' => $_POST[ 'admin_email' ] ?? '',
        ];

        $parentDir = dirname( __DIR__ );

        // 1. Dependencies should be already included in the zip
        if ( !file_exists( $parentDir . '/vendor/autoload.php' ) ) {
            echo json_encode( [
                'success' => false,
                'message' => 'vendor/autoload.php not found. The archive seems incomplete.',
            ] );
            exit;
        }

        // 2. Run the artisan install command in-process (no shell exec required)
        $artisan = $parentDir . '/artisan';

        if ( file_exists( $artisan ) ) {
            $result = runArtisanInstall( $parentDir, $_SESSION[ 'site_details' ] ?? [] );
            echo json_encode( $result );
        }
        else {
            echo json_encode( [ 'success' => false, 'message' => 'Artisan file not found at ' . $artisan ] );
        }
        exit;
    }

    if ( $action === 'delete_installer' ) {
        /**
         * Recursively delete a directory
         */
        $deleteRecursive = function ( $dir ) use ( &$deleteRecursive ) {
            if ( !file_exists( $dir ) ) {
                return true;
            }

            if ( !is_dir( $dir ) ) {
                return unlink( $dir );
            }

            foreach ( scandir( $dir ) as $item ) {
                if ( $item == '.' || $item == '..' ) {
                    continue;
                }

                if ( !$deleteRecursive( $dir . DIRECTORY_SEPARATOR . $item ) ) {
                    return false;
                }
            }

            return rmdir( $dir );
        };

        $installerDir = __DIR__;

        // Start deletion. Note: on some systems, the script might be locked while running.
        // But usually, we can delete the directory and its files even if this script is currently executing.
        // We will try to delete everything except this script first, and then this script as the last step.

        $success = true;
        foreach ( scandir( $installerDir ) as $item ) {
            if ( $item == '.' || $item == '..' ) {
                continue;
            }

            $path = $installerDir . DIRECTORY_SEPARATOR . $item;

            if ( $path === __FILE__ ) {
                continue; // Skip this file for now
            }

            if ( !$deleteRecursive( $path ) ) {
                $success = false;
            }
        }

        // Finally, try to delete this file and the directory
        if ( $success ) {
            // We can't easily delete the directory if the script is still running, and it's inside it,
            // but we can try to schedule it or just unlink this file.
            @unlink( __FILE__ );
            @rmdir( $installerDir );
            echo json_encode( [ 'success' => true ] );
        }
        else {
            echo json_encode( [ 'success' => false, 'message' => 'Failed to delete some files in the installer directory. Please delete it manually.' ] );
        }
        exit;
    }
}

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ValPress Installation Wizard</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <style>
        body {
            background-color: #f8f9fa;
        }

        .installer-container {
            max-width: 700px;
            margin: 50px auto;
        }

        .card {
            border: none;
            box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
        }

        .step-header {
            background-color: #0d6efd;
            color: white;
            padding: 20px;
            border-radius: 0.25rem 0.25rem 0 0;
        }

        .bi {
            vertical-align: -.125em;
            fill: currentColor;
        }
    </style>
</head>
<body>

    <div class="installer-container">
        <div class="card">
            <?php if ( $step === 0 ): ?>
                <div class="step-header text-center">
                    <h2 class="mb-0">Welcome to ValPress</h2>
                </div>
                <div class="card-body text-center p-5">
                    <p class="lead">Thank you for choosing ValPress CMS. Let's get your site up and running in just a
                                    few steps.</p>
                    <a href="?step=1" class="btn btn-primary btn-lg px-5 mt-3">Start Installation</a>
                </div>

            <?php elseif ( $step === 1 ):
                $res = checkRequirements( $requirements );
                ?>
                <div class="step-header">
                    <h4 class="mb-0">Step 1: Requirements Check</h4>
                </div>
                <div class="card-body">
                    <table class="table align-middle">
                        <thead>
                            <tr>
                                <th>Requirement</th>
                                <th>Required</th>
                                <th>Current</th>
                                <th class="text-center">Status</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ( $res[ 'details' ] as $detail ): ?>
                                <tr>
                                    <td><?php echo $detail[ 'name' ]; ?></td>
                                    <td><?php echo $detail[ 'required' ]; ?></td>
                                    <td><?php echo $detail[ 'current' ]; ?></td>
                                    <td class="text-center">
                                        <?php if ( $detail[ 'status' ] ): ?>
                                            <span class="text-success">✔</span>
                                        <?php else: ?>
                                            <span class="text-danger">✘</span>
                                        <?php endif; ?>
                                    </td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                    <div class="mt-4 d-flex justify-content-between">
                        <a href="?step=0" class="btn btn-outline-secondary">Back</a>
                        <?php if ( $res[ 'compatible' ] ): ?>
                            <button id="btn-extract" class="btn btn-primary">Proceed to Extraction</button>
                        <?php else: ?>
                            <button class="btn btn-primary" disabled>Requirements Not Met</button>
                        <?php endif; ?>
                    </div>
                </div>

            <?php elseif ( $step === 2 ): ?>
                <div class="step-header">
                    <h4 class="mb-0">Step 2: Database Configuration</h4>
                </div>
                <div class="card-body">
                    <form id="db-form">
                        <div class="mb-3">
                            <label class="form-label">Site URL</label>
                            <input type="text" name="site_url" class="form-control" value="<?php echo 'http://' . $_SERVER[ 'HTTP_HOST' ]; ?>" required>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">Database Connection</label>
                            <select name="db_connection" id="db_connection" class="form-select" required>
                                <option value="mysql">MySQL</option>
                                <option value="mariadb">MariaDB</option>
                                <option value="pgsql">PostgreSQL</option>
                                <option value="sqlsrv">SQL Server (Windows)</option>
                                <option value="sqlite">SQLite</option>
                            </select>
                        </div>
                        <div class="db-details">
                            <div class="mb-3">
                                <label class="form-label">Database Host</label>
                                <input type="text" name="db_host" id="db_host" class="form-control" value="localhost">
                            </div>
                            <div class="mb-3">
                                <label class="form-label">Database Port</label>
                                <input type="text" name="db_port" id="db_port" class="form-control" value="3306">
                            </div>
                        </div>
                        <div class="mb-3">
                            <label class="form-label" id="db_name_label">Database Name</label>
                            <input type="text" name="db_name" id="db_name" class="form-control" required>
                            <div id="sqlite-hint" class="form-text d-none">For SQLite, provide the absolute path or
                                                                           relative to project root (e.g.,
                                                                           database/database.sqlite).
                            </div>
                        </div>
                        <div class="db-details">
                            <div class="mb-3">
                                <label class="form-label">Username</label>
                                <input type="text" name="db_user" id="db_user" class="form-control">
                            </div>
                            <div class="mb-3">
                                <label class="form-label">Password</label>
                                <input type="password" name="db_pass" id="db_pass" class="form-control">
                            </div>
                        </div>
                        <div id="db-error" class="alert alert-danger d-none"></div>
                        <div class="mt-4 d-flex justify-content-between">
                            <a href="?step=1" class="btn btn-outline-secondary">Back</a>
                            <button type="submit" class="btn btn-primary">Test Connection & Next</button>
                        </div>
                    </form>
                </div>

            <?php elseif ( $step === 3 ): ?>
                <div class="step-header">
                    <h4 class="mb-0">Step 3: Site Details</h4>
                </div>
                <div class="card-body">
                    <form id="site-form">
                        <div class="mb-3">
                            <label class="form-label">Site Name</label>
                            <input type="text" name="site_name" class="form-control" placeholder="My ValPress Site" required>
                        </div>
                        <hr>
                        <h5>Admin Account</h5>
                        <div class="mb-3">
                            <label class="form-label">Username</label>
                            <input type="text" name="admin_user" class="form-control" value="admin" required>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">Password</label>
                            <input type="password" name="admin_pass" class="form-control" required>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">Email Address</label>
                            <input type="email" name="admin_email" class="form-control" required>
                        </div>
                        <div id="install-error" class="alert alert-danger d-none"></div>
                        <div class="mt-4 d-flex justify-content-between">
                            <a href="?step=2" class="btn btn-outline-secondary">Back</a>
                            <button type="submit" class="btn btn-success">Install ValPress</button>
                        </div>
                    </form>
                </div>

            <?php elseif ( $step === 4 ): ?>
                <div class="step-header text-center bg-success">
                    <h2 class="mb-0">Installation Successful!</h2>
                </div>
                <div class="card-body text-center p-5">
                    <p class="lead">ValPress has been successfully installed.</p>
                    <div id="installer-cleanup-section">
                        <div class="alert alert-warning">
                            For security reasons, please delete the <code>installer</code> directory from your server.
                        </div>
                        <button id="btn-delete-installer" class="btn btn-danger btn-lg px-5 mb-3">Delete Installer Directory</button>
                        <div class="mt-2">
                            <a href="../" class="btn btn-link">I'll do it manually, go to my site</a>
                        </div>
                    </div>
                    <div id="final-redirect-section" class="d-none">
                        <div class="alert alert-success">
                            Installer directory deleted successfully.
                        </div>
                        <a href="../" class="btn btn-primary btn-lg px-5">Go to Your Site</a>
                    </div>
                </div>
            <?php endif; ?>
        </div>
    </div>

    <script src="js/jquery.min.js"></script>
    <script>
        $( function () {
            $( '#db_connection' ).change( function () {
                const conn = $( this ).val();
                const $details = $( '.db-details' );
                const $dbNameLabel = $( '#db_name_label' );
                const $sqliteHint = $( '#sqlite-hint' );
                const $host = $( '#db_host' );
                const $port = $( '#db_port' );
                const $user = $( '#db_user' );

                if ( conn === 'sqlite' ) {
                    $details.addClass( 'd-none' );
                    $dbNameLabel.text( 'Database File Path' );
                    $sqliteHint.removeClass( 'd-none' );
                    $( '#db_name' ).val( 'database/database.sqlite' );
                    $host.prop( 'required', false );
                    $user.prop( 'required', false );
                }
                else {
                    $details.removeClass( 'd-none' );
                    $dbNameLabel.text( 'Database Name' );
                    $sqliteHint.addClass( 'd-none' );
                    $host.prop( 'required', true );
                    $user.prop( 'required', true );

                    if ( conn === 'pgsql' ) {
                        $port.val( '5432' );
                    }
                    else if ( conn === 'sqlsrv' ) {
                        $port.val( '1433' );
                    }
                    else {
                        $port.val( '3306' );
                    }
                }
            } ).trigger( 'change' );

            $( '#btn-extract' ).click( function () {
                const $btn = $( this );
                $btn.prop( 'disabled', true ).html( '<span class="spinner-border spinner-border-sm me-2"></span>Extracting...' );

                $.ajax( {
                    url: '',
                    method: 'POST',
                    data: { action: 'extract' },
                    dataType: 'json',
                    timeout: 0, // No timeout for extraction
                    success: function (response) {
                        if ( response.success ) {
                            window.location.href = '?step=2';
                        }
                        else {
                            alert( response.message );
                            $btn.prop( 'disabled', false ).text( 'Proceed to Extraction' );
                        }
                    },
                    error: function (xhr, status, error) {
                        let msg = 'Extraction failed: ' + status + ' ' + error;
                        if ( xhr.responseText ) {
                            msg += '\n\nResponse: ' + xhr.responseText.substring( 0, 200 );
                        }
                        alert( msg );
                        $btn.prop( 'disabled', false ).text( 'Proceed to Extraction' );
                    }
                } );
            } );

            $( '#db-form' ).submit( function (e) {
                e.preventDefault();
                const $btn = $( this ).find( 'button[type="submit"]' );
                $btn.prop( 'disabled', true ).text( 'Testing...' );
                $( '#db-error' ).addClass( 'd-none' );

                const data = $( this ).serialize() + '&action=test_db';

                $.post( '', data, function (response) {
                    if ( response.success ) {
                        $.post( '', { action: 'setup_env' }, function (envResponse) {
                            if ( envResponse.success ) {
                                window.location.href = '?step=3';
                            }
                            else {
                                $( '#db-error' ).text( envResponse.message ).removeClass( 'd-none' );
                                $btn.prop( 'disabled', false ).text( 'Test Connection & Next' );
                            }
                        }, 'json' );
                    }
                    else {
                        $( '#db-error' ).text( response.message ).removeClass( 'd-none' );
                        $btn.prop( 'disabled', false ).text( 'Test Connection & Next' );
                    }
                }, 'json' );
            } );

            $( '#site-form' ).submit( function (e) {
                e.preventDefault();
                const $btn = $( this ).find( 'button[type="submit"]' );
                $btn.prop( 'disabled', true ).text( 'Installing...' );
                $( '#install-error' ).addClass( 'd-none' );

                const data = $( this ).serialize() + '&action=install';

                $.post( '', data, function (response) {
                    if ( response.success ) {
                        window.location.href = '?step=4';
                    }
                    else {
                        $( '#install-error' ).text( response.message ).removeClass( 'd-none' );
                        $btn.prop( 'disabled', false ).text( 'Install ValPress' );
                    }
                }, 'json' );
            } );

            $( '#btn-delete-installer' ).click( function () {
                if ( !confirm( 'Are you sure you want to delete the installer directory? This action cannot be undone.' ) ) {
                    return;
                }

                const $btn = $( this );
                $btn.prop( 'disabled', true ).html( '<span class="spinner-border spinner-border-sm me-2"></span>Deleting...' );

                $.post( '', { action: 'delete_installer' }, function (response) {
                    if ( response.success ) {
                        $( '#installer-cleanup-section' ).addClass( 'd-none' );
                        $( '#final-redirect-section' ).removeClass( 'd-none' );
                    }
                    else {
                        alert( response.message );
                        $btn.prop( 'disabled', false ).text( 'Delete Installer Directory' );
                    }
                }, 'json' );
            } );
        } );
    </script>
</body>
</html>
