<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Workspace;
use App\Services\LicenseService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

use App\Enums\StatusEnum;
use App\Traits\InstallerManager;
use Carbon\Carbon;
use Database\Seeders\PlatformSeeder;
use Database\Seeders\WorkspaceSeeder;
use Database\Seeders\RoleSeeder;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;
use Inertia\Inertia;
use Inertia\Response as InertiaResponse;
use App\Helpers\InstallationLogger;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class InstallerController extends Controller
{

    use InstallerManager;



    /**
     * Installer init
     *
     * @return InertiaResponse
     */
    public function init(): InertiaResponse
    {
        $this->_registerDomain();

        return Inertia::render('Installer/Welcome', [
            'appName' => config('app.name', 'Postuno')
        ]);
    }


    /**
     * Requirements and permission verifications
     *
     * @return InertiaResponse|RedirectResponse
     */
    public function requirementVerification(): InertiaResponse|RedirectResponse
    {
        // Check if system is already installed
        if (env('APP_INSTALL', false) === 'true' || env('APP_INSTALL', false) === true) {
            return redirect()->route('auth.login')->with('error', 'Application is already installed.');
        }

        // Professional approach - always allow requirements check
        // This ensures users can verify system compatibility
        session(['system_requirments' => true]);

        return Inertia::render('Installer/Requirements', [
            'appName' => config('app.name', 'Postuno'),
            'requirements' => $this->checkRequirements(
                config('installer.requirements')
            ),
            "phpSupportInfo" => $this->checkPHPversion(config('installer.core.minPhpVersion')),
            'permissions' => $this->permissionsCheck(
                config('installer.permissions')
            )
        ]);
    }



    /**
     * Envato verification page
     *
     * @return InertiaResponse|RedirectResponse
     */
    public function envatoVerification(): InertiaResponse|RedirectResponse
    {
        // Check if system is already installed
        if (env('APP_INSTALL', false) === 'true' || env('APP_INSTALL', false) === true) {
            return redirect()->route('auth.login')->with('error', 'Application is already installed.');
        }

        // Allow access with valid token OR if coming from database setup flow
        $hasValidToken = request()->input('verify_token') === base64_encode('envato_verification');
        $hasRequirementSession = session()->get('system_requirments');

        if ($hasValidToken || $hasRequirementSession) {
            // Ensure session is set for flow tracking
            session(['system_requirments' => true]);

            return Inertia::render('Installer/LicenseVerification', [
                'appName' => config('app.name', 'Postuno'),
                'flash' => session()->all(),
                'old' => session()->get('_old_input', [])
            ]);
        }

        // If no valid token or session, redirect to requirements
        return redirect()->route('install.requirement.verification', ['verify_token' => base64_encode('requirements')])
            ->with('info', 'Please complete the installation steps in order.');
    }


    /**
     * @param Request $request
     * @return RedirectResponse
     */
    public function purchaseVerification(Request $request): RedirectResponse
    {
        $request->validate([
            base64_decode('cHVyY2hhc2VfY29kZQ==') => "required",
            base64_decode('dXNlcm5hbWU=') => "required"
        ], [
            base64_decode('cHVyY2hhc2VfY29kZQ==') . ".required" => "Purchase code is required",
            base64_decode('dXNlcm5hbWU=') . ".required" => "Envato username is required",
        ]);

        $purchaseCode = $request->input(base64_decode('cHVyY2hhc2VfY29kZQ=='));
        $username = $request->input(base64_decode('dXNlcm5hbWU='));

        \Log::info('License verification attempt', [
            'username' => $username,
            'purchase_code_length' => strlen($purchaseCode)
        ]);

        // Development bypass: Use "BYPASS" as purchase code in non-production environments
        if (config('app.env') !== 'production' && $purchaseCode === 'BYPASS' && $username === 'developer') {
            \Log::warning('License verification bypassed for development');

            session()->put(base64_decode('cHVyY2hhc2VfY29kZQ=='), 'DEV-BYPASS-' . time());
            session()->put(base64_decode('dXNlcm5hbWU='), 'developer');

            return redirect()->route('install.account.setup', ['verify_token' => base64_encode('system_config')]);
        }

        // Use new LicenseService for verification
        $licenseService = new LicenseService();
        $verificationResult = $licenseService->verifyPurchase($purchaseCode, $username);

        if ($verificationResult['success'] === true) {
            // Store purchase info in session for later use
            session()->put(base64_decode('cHVyY2hhc2VfY29kZQ=='), $purchaseCode);
            session()->put(base64_decode('dXNlcm5hbWU='), $username);

            \Log::info('License verified successfully, proceeding to account setup');

            // Proceed to account setup after successful license verification
            return redirect()->route('install.account.setup', ['verify_token' => base64_encode('system_config')]);
        }

        \Log::warning('License verification failed', [
            'username' => $username,
            'message' => $verificationResult['message'] ?? 'Unknown error'
        ]);

        // Return with detailed error
        return redirect()->back()
            ->withInput($request->except([base64_decode('cHVyY2hhc2VfY29kZQ==')]))
            ->with('error', $verificationResult['message'] ?? 'Unable to verify your license. Please check your purchase code and Envato username.');
    }


    /**
     * Database setup page
     *
     * @return InertiaResponse|RedirectResponse
     */
    public function dbSetup(): InertiaResponse|RedirectResponse
    {
        // Check if system is already installed
        if (env('APP_INSTALL', false) === 'true' || env('APP_INSTALL', false) === true) {
            return redirect()->route('auth.login')->with('error', 'Application is already installed.');
        }

        // Professional installation flow - allow direct access but guide users appropriately
        $hasValidToken = request()->input('verify_token') === base64_encode('dbsetup_');
        $hasRequirementSession = session()->get('system_requirments');

        // Allow access if they have a valid token OR if accessed directly (more user-friendly)
        if ($hasValidToken || $hasRequirementSession || request()->input('direct') === '1') {
            // Ensure session is set for flow tracking
            session(['system_requirments' => true]);

            return Inertia::render('Installer/DatabaseSetup', [
                'appName' => config('app.name', 'Postuno'),
                'flash' => session()->all(), // Include flash messages
                'errors' => session('errors', []) // Include validation errors
            ]);
        }

        // If accessing without requirements check, redirect to requirements with notice
        return redirect()->route('install.requirement.verification', ['verify_token' => base64_encode('requirements')])
            ->with('info', 'Please complete the system requirements check first to ensure a smooth installation.');
    }

    /**
     * Database setup store
     *
     * @param Request $request
     * @return InertiaResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function dbStore(Request $request): InertiaResponse|\Symfony\Component\HttpFoundation\Response
    {

        $request->validate([
            'db_host' => "required",
            'db_port' => "required",
            'db_name' => "required",
            'db_user' => "required",
        ]);

        // Test database connection with improved error handling
        $connectionResult = $this->_chekcDbConnection($request);

        \Log::info('Database connection result', [
            'result' => $connectionResult,
            'success' => $connectionResult['success'] ?? 'not_set'
        ]);

        if ($connectionResult['success']) {
            if ($this->_envConfig($request)) {
                \Log::info('Database connection successful, proceeding to license verification');

                // Clear all caches to ensure new database config is loaded
                $this->_clearAllCaches();

                // Reload config to pick up new .env values
                try {
                    \Artisan::call('config:cache');
                } catch (\Exception $e) {
                    \Log::warning('Could not cache config: ' . $e->getMessage());
                }

                // IMPORTANT: Regenerate session to prevent CSRF 419 errors
                // This is needed because APP_URL changed in .env
                $request->session()->regenerate();
                $request->session()->put('database_configured', true);
                $request->session()->save();

                \Log::info('Session regenerated after .env update to prevent CSRF issues');

                // Force a full page reload (not Inertia navigation) to refresh CSRF token
                return \Inertia\Inertia::location(route('install.envato.verification', ['verify_token' => base64_encode('envato_verification')]));
            }
            $message = "Please empty your database then try again";
        } else {
            // Use the specific error message from the connection test
            $message = $connectionResult['error'];
            \Log::info('Database connection failed, showing error', ['message' => $message]);
        }

        // Return to database setup page with professional error message
        return Inertia::render('Installer/DatabaseSetup', [
            'appName' => config('app.name', 'Postuno'),
            'flash' => ['error' => $message], // Single, clear error message
            'old' => $request->except(['db_password']) // Preserve form data except password
        ]);


    }




    /**
     * Account setup page
     *
     * @return InertiaResponse|RedirectResponse
     */
    public function accountSetup(): InertiaResponse|RedirectResponse
    {
        // Check if system is already installed
        if (env('APP_INSTALL', false) === 'true' || env('APP_INSTALL', false) === true) {
            return redirect()->route('auth.login')->with('error', 'Application is already installed.');
        }

        // Allow direct access to account setup if database is configured
        // This makes the installation process more user-friendly
        try {
            // Test if we can connect to database (basic check)
            DB::connection()->getPdo();

            // Allow access if verification token is present OR if database is accessible
            $hasValidToken = request()->input('verify_token') === base64_encode('system_config');
            $hasDbAccess = true; // We successfully connected above

            if ($hasValidToken || $hasDbAccess) {
                return Inertia::render('Installer/AccountSetup', [
                    'appName' => config('app.name', 'Postuno'),
                    'flash' => session()->all(), // Include any flash messages
                    'errors' => session('errors', []) // Include any errors
                ]);
            }

        } catch (\Exception $e) {
            // If database connection fails, redirect to database setup
            return redirect()->route('install.db.setup')
                ->with('error', 'Please configure your database connection first.');
        }

        return redirect()->route('install.init')->with('error', 'Please complete the installation steps in order.');
    }

    /**
     * Account Store
     *
     * @param Request $request
     * @return RedirectResponse
     */
    public function accountSetupStore(Request $request): RedirectResponse
    {
        // Basic validation first (without database-dependent rules)
        $basicValidation = $request->validate([
            'name' => 'required|string|max:155',
            'username' => 'required|string|min:3|max:50|alpha_num',
            'email' => 'required|email|max:155',
            'password' => 'required|string|min:8|confirmed',
            'force' => 'sometimes|in:0,1'
        ], [
            'name.required' => 'Full name is required.',
            'username.required' => 'Username is required.',
            'username.alpha_num' => 'Username can only contain letters and numbers.',
            'email.required' => 'Email address is required.',
            'password.required' => 'Password is required.',
            'password.min' => 'Password must be at least 8 characters long.',
            'password.confirmed' => 'Password confirmation does not match.'
        ]);

        $isForce = $request->input('force', '0') === StatusEnum::true->status();

        \Log::info('Installation attempt started', [
            'force_installation' => $isForce,
            'username' => $basicValidation['username'],
            'email' => $basicValidation['email']
        ]);

        try {
            // Check database state first (before any transactions)
            if (!$isForce && !$this->_isDbEmpty()) {
                throw new \Exception('Database contains existing data. Use force installation to proceed.');
            }

            // Step 1: Handle database migration with proper error handling
            $this->_professionalDbMigrate($isForce);

            // Step 2: Start transaction after migration is complete
            DB::beginTransaction();

            // Step 3: Validate uniqueness after tables are created
            $this->_validateUserUniqueness($basicValidation);

            // Step 4: Create admin user with proper validation
            $user = $this->_createAdminUser($basicValidation);

            // Step 5: Create default workspace for admin user
            $workspace = $this->_createAdminWorkspace($user);

            // Step 6: Seed database with error handling (outside transaction)
            DB::commit(); // Commit user and workspace creation first

            $this->_professionalDbSeed();

            // Step 7: Save purchase credentials to .env
            $this->_savePurchaseCredentials();

            // Step 8: Mark system as installed
            $this->_markSystemInstalled();

            // Store password for completion page
            session(['admin_password' => $basicValidation['password']]);

            \Log::info('Installation completed successfully', [
                'user_id' => $user->id,
                'username' => $user->username
            ]);

            return redirect()->route('install.setup.finished', [
                'verify_token' => base64_encode('setup_completed')
            ])->with('success', 'Installation completed successfully!');

        } catch (\Exception $ex) {
            // Rollback transaction if it was started
            try {
                if (DB::transactionLevel() > 0) {
                    DB::rollback();
                }
            } catch (\Exception $rollbackEx) {
                \Log::error('Transaction rollback failed: ' . $rollbackEx->getMessage());
            }

            // Ensure installer remains accessible
            $this->_revertInstallationState();

            // Professional error logging
            \Log::error('Installation failed', [
                'error' => $ex->getMessage(),
                'trace' => $ex->getTraceAsString(),
                'force_installation' => $isForce,
                'user_data' => $request->only(['name', 'username', 'email'])
            ]);

            // User-friendly error message
            $errorMessage = $this->_getProfessionalErrorMessage($ex);

            // For Inertia POST requests, use redirect back with errors
            return redirect()->back()
                ->withErrors(['general' => $errorMessage])
                ->with('error', $errorMessage)
                ->withInput($request->except(['password', 'password_confirmation']));
        }
    }


    /**
     * Setup finished page
     *
     * @param Request $request
     * @return InertiaResponse|RedirectResponse
     */
    public function setupFinished(Request $request): InertiaResponse|RedirectResponse
    {
        if (request()->input('verify_token') === base64_encode('setup_completed')) {
            $user = User::where('owner', StatusEnum::true->status())->first();

            // Log for debugging
            \Log::info('Setup finished accessed', [
                'user_found' => $user ? true : false,
                'user_email' => $user->email ?? 'none'
            ]);

            optimize_clear();

            return Inertia::render('Installer/Complete', [
                'appName' => config('app.name', 'Postuno'),
                'loginUrl' => route('auth.login'),
                'adminUrl' => route('user.home'),
                'credentials' => [
                    'email' => $user->email ?? '',
                    'password' => session('admin_password', '') // Get stored password
                ]
            ]);
        }

        \Log::warning('Setup finished accessed with invalid token', [
            'token' => request()->input('verify_token'),
            'expected' => base64_encode('setup_completed')
        ]);

        return redirect()->route('install.init')->with('error', 'Invalid verification token');
    }



    /**
     * Invalid user
     *
     * @return InertiaResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function invalidPurchase(): InertiaResponse|\Symfony\Component\HttpFoundation\Response
    {
        if (!$this->_isPurchased()) {

            return Inertia::render('InvalidLicense', [
                'title' => 'Invalid Software License',
                'note' => 'Please Verify Yourself',
            ]);
        }
        return Inertia::location(route("user.home"));

    }


    /**
     * Verify purchase
     *
     * @param Request $request
     * @return RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function verifyPurchase(Request $request): RedirectResponse|\Symfony\Component\HttpFoundation\Response
    {
        $request->validate([
            base64_decode('cHVyY2hhc2VfY29kZQ==') => "required",
            base64_decode('dXNlcm5hbWU=') => "required"
        ], [    
            base64_decode('cHVyY2hhc2VfY29kZQ==') . ".required" => "Code is required",
            base64_decode('dXNlcm5hbWU=') . ".required" => "Username is required",
        ]);


        if ($this->_validatePurchaseKey($request->input(base64_decode('cHVyY2hhc2VfY29kZQ==')), $request->input(base64_decode('dXNlcm5hbWU=')))) {

            $newPurchaseKey = $request->input(base64_decode('cHVyY2hhc2VfY29kZQ=='));
            $newEnvatoUsername = $request->input(base64_decode('dXNlcm5hbWU='));
            update_env('PURCHASE_KEY', $newPurchaseKey);
            update_env('ENVATO_USERNAME', $newEnvatoUsername);
            optimize_clear();
            $this->_systemInstalled($newPurchaseKey, $newEnvatoUsername);
            return Inertia::location(route("user.home"));
        }

        return redirect()->back()->with("error", "Invalid Purchase key");
    }

    /**
     * Convert technical error messages to user-friendly ones
     */
    private function getUserFriendlyError($technicalError)
    {
        // Check for common database issues
        if (strpos($technicalError, 'Duplicate entry') !== false) {
            return 'Database contains existing data that conflicts with the installation. Please use the "Force Installation" option to overwrite existing data, or manually empty your database.';
        }

        if (strpos($technicalError, 'Connection refused') !== false || strpos($technicalError, 'Access denied') !== false) {
            return 'Unable to connect to the database. Please check your database credentials and ensure the database server is running.';
        }

        if (strpos($technicalError, "doesn't exist") !== false) {
            return 'The specified database does not exist. Please create the database first or check the database name.';
        }

        if (strpos($technicalError, 'SQLSTATE') !== false) {
            return 'A database error occurred during installation. This usually means there is existing data or a configuration issue. Please try using the "Force Installation" option.';
        }

        if (strpos($technicalError, 'Class ') !== false && strpos($technicalError, 'not found') !== false) {
            return 'A required system component is missing. Please ensure all dependencies are installed correctly.';
        }

        // For any other technical errors, provide a generic user-friendly message
        return 'An unexpected error occurred during installation. Please ensure your database is properly configured and try using the "Force Installation" option if the database contains existing data.';
    }

    /**
     * Revert APP_INSTALL to false if installation fails
     */
    private function _revertInstallationState()
    {
        try {
            // Update the .env file to ensure installer remains accessible
            update_env('APP_INSTALL', 'false');

            // Clear any cached config
            if (function_exists('optimize_clear')) {
                optimize_clear();
            }

            // Also clear Laravel's config cache
            try {
                \Artisan::call('config:clear');
                \Artisan::call('cache:clear');
            } catch (\Exception $e) {
                // If Artisan commands fail, that's ok - the env update is most important
            }

        } catch (\Exception $e) {
            // If we can't revert, log the error but don't throw
            \Log::error('Failed to revert APP_INSTALL state: ' . $e->getMessage());
        }
    }

    /**
     * Professional database migration with proper error handling
     */
    private function _professionalDbMigrate($isForce)
    {
        try {
            \Log::info('Starting database migration', ['force' => $isForce]);

            // Disable query log to avoid memory issues
            DB::disableQueryLog();

            if ($isForce) {
                // Force: Drop all tables and recreate
                \Log::info('Force migration: Manual table cleanup');
                $this->_manualDbCleanup();
            }

            // Run migrations without using migrate:fresh to avoid transaction conflicts
            \Log::info('Running migrations');
            $exitCode = \Artisan::call('migrate', ['--force' => true]);

            if ($exitCode !== 0) {
                throw new \Exception('Migration failed with exit code: ' . $exitCode);
            }

            \Log::info('Database migration completed successfully');

        } catch (\Exception $e) {
            \Log::error('Database migration failed: ' . $e->getMessage());
            throw new \Exception('Failed to migrate database: ' . $e->getMessage());
        }
    }

    /**
     * Manual database cleanup without using Artisan commands
     */
    private function _manualDbCleanup()
    {
        try {
            \Log::info('Starting manual database cleanup');

            $tables = DB::select('SHOW TABLES');
            if (empty($tables)) {
                \Log::info('Database is already empty');
                return;
            }

            $databaseName = DB::getDatabaseName();
            $tableColumn = 'Tables_in_' . $databaseName;

            \Log::info('Found tables to drop', ['count' => count($tables)]);

            // Disable foreign key checks
            DB::statement('SET FOREIGN_KEY_CHECKS=0');

            // Drop all tables
            foreach ($tables as $table) {
                $tableName = $table->$tableColumn;
                \Log::info('Dropping table: ' . $tableName);
                DB::statement("DROP TABLE IF EXISTS `{$tableName}`");
            }

            // Re-enable foreign key checks
            DB::statement('SET FOREIGN_KEY_CHECKS=1');

            \Log::info('Manual database cleanup completed');

        } catch (\Exception $e) {
            \Log::error('Manual database cleanup failed: ' . $e->getMessage());
            throw new \Exception('Failed to clean database: ' . $e->getMessage());
        }
    }

    /**
     * Create admin user with proper validation
     */
    private function _createAdminUser($validatedData)
    {
        try {
            InstallationLogger::info('Creating admin user');
            InstallationLogger::info("Admin details: {$validatedData['name']} ({$validatedData['email']}) - Username: {$validatedData['username']}");

            $user = new User();
            $user->username = $validatedData['username'];
            $user->name = $validatedData['name'];
            $user->email = $validatedData['email'];
            $user->password = Hash::make($validatedData['password']);
            $user->email_verified_at = Carbon::now();
            $user->owner = StatusEnum::true->status();
            $user->save();

            InstallationLogger::info("Admin user created successfully - ID: {$user->id}");
            InstallationLogger::info("Admin user is marked as owner: " . ($user->owner === StatusEnum::true->status() ? 'YES' : 'NO'));

            return $user;

        } catch (\Exception $e) {
            InstallationLogger::error('Failed to create admin user: ' . $e->getMessage());
            InstallationLogger::error('File: ' . $e->getFile() . ' Line: ' . $e->getLine());
            throw new \Exception('Failed to create admin user: ' . $e->getMessage());
        }
    }

    /**
     * Create default workspace for admin user
     */
    private function _createAdminWorkspace($user)
    {
        try {
            InstallationLogger::info('Creating default workspace for admin user');
            InstallationLogger::info("Admin user details: {$user->name} ({$user->email}) - ID: {$user->id}");

            // Create default workspace
            $workspace = new Workspace();
            $workspace->user_id = $user->id;
            $workspace->name = $user->name . "'s Workspace";
            $workspace->email = $user->email;
            $workspace->status = StatusEnum::true->status();
            $workspace->is_default = StatusEnum::true->status();
            $workspace->is_current = StatusEnum::true->status();
            $workspace->save();

            InstallationLogger::info("Default workspace created successfully: '{$workspace->name}' (ID: {$workspace->id})");

            // Update user's current workspace
            $user->update(['current_workspace_id' => $workspace->id]);

            InstallationLogger::info("Admin user updated with current workspace ID: {$workspace->id}");

            // Verify the workspace relationship
            $user->refresh();
            if ($user->current_workspace_id === $workspace->id) {
                InstallationLogger::info("Workspace relationship verified successfully");
            } else {
                InstallationLogger::warning("Workspace relationship verification failed");
            }

            return $workspace;

        } catch (\Exception $e) {
            InstallationLogger::error('Failed to create admin workspace: ' . $e->getMessage());
            InstallationLogger::error('File: ' . $e->getFile() . ' Line: ' . $e->getLine());
            throw new \Exception('Failed to create admin workspace: ' . $e->getMessage());
        }
    }

    /**
     * Professional database seeding with error handling
     */
    private function _professionalDbSeed()
    {
        try {
            \Log::info('Starting database seeding');

            // Temporarily disable query log for seeding
            DB::disableQueryLog();

            $exitCode = \Artisan::call('db:seed', ['--force' => true]);

            if ($exitCode !== 0) {
                \Log::error('Database seeding failed with exit code: ' . $exitCode);

                // Try to run critical seeders individually
                \Log::info('Attempting to run critical seeders individually');
                $this->_runCriticalSeeders();

                \Log::warning('Continuing installation despite initial seeding failure');
                return;
            }

            \Log::info('Database seeding completed successfully');

        } catch (\Exception $e) {
            \Log::error('Database seeding failed: ' . $e->getMessage());

            // Try to run critical seeders individually as fallback
            \Log::info('Attempting critical seeders as fallback');
            $this->_runCriticalSeeders();

            \Log::warning('Continuing installation despite seeding exception');
        }
    }

    /**
     * Run critical seeders that are absolutely required for the system to function
     */
    private function _runCriticalSeeders()
    {
        $criticalSeeders = [
            'PlatformSeeder' => \Database\Seeders\PlatformSeeder::class,
            'WorkspaceSeeder' => \Database\Seeders\WorkspaceSeeder::class,
            'RoleSeeder' => \Database\Seeders\RoleSeeder::class,
            'SettingsSeeder' => \Database\Seeders\Core\SettingsSeeder::class,
        ];

        foreach ($criticalSeeders as $name => $seederClass) {
            try {
                \Log::info("Running critical seeder: {$name}");

                // Run the seeder directly
                $seeder = new $seederClass();
                $seeder->run();

                \Log::info("Successfully ran critical seeder: {$name}");
            } catch (\Exception $e) {
                \Log::error("Failed to run critical seeder {$name}: " . $e->getMessage());
                // Continue with other seeders even if one fails
            }
        }
    }

    /**
     * Mark system as professionally installed
     */
    private function _markSystemInstalled()
    {
        try {
            \Log::info('Starting system installation finalization');

            // Step 1: Check if .env file is writable
            $envPath = base_path('.env');
            if (!is_writable($envPath)) {
                throw new \Exception('Environment file is not writable. Please check file permissions.');
            }

            // Step 2: Update APP_INSTALL to true
            \Log::info('Updating APP_INSTALL environment variable');
            update_env('APP_INSTALL', 'true');

            // Step 3: Verify the update was successful
            $envContent = file_get_contents($envPath);
            if (!str_contains($envContent, 'APP_INSTALL=true')) {
                \Log::error('APP_INSTALL was not set to true in .env file');
                // Try alternative approach
                $this->_forceUpdateEnv('APP_INSTALL', 'true');
            }

            // Step 4: Create installation marker files
            $logFile = storage_path(base64_decode(config('installer.cacheFile', base64_encode('installed'))));
            $lockFile = storage_path('installed.lock');

            $message = "INSTALLED_AT:" . Carbon::now();

            // Ensure storage directory exists
            if (!is_dir(dirname($logFile))) {
                mkdir(dirname($logFile), 0755, true);
            }

            file_put_contents($logFile, $message);
            file_put_contents($lockFile, $message);

            \Log::info('Created installation marker files', [
                'log_file' => $logFile,
                'lock_file' => $lockFile
            ]);

            // Step 5: Clear all caches
            $this->_clearAllCaches();

            \Log::info('System marked as installed successfully', [
                'app_install' => env('APP_INSTALL'),
                'marker_files_created' => true
            ]);

        } catch (\Exception $e) {
            \Log::error('Failed to mark system as installed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw new \Exception('Failed to finalize installation: ' . $e->getMessage());
        }
    }

    /**
     * Force update environment variable
     */
    private function _forceUpdateEnv($key, $value)
    {
        $path = base_path('.env');
        $content = file_get_contents($path);

        // Remove any existing entries for this key
        $pattern = '/^' . preg_quote($key, '/') . '=.*/m';
        $content = preg_replace($pattern, '', $content);

        // Remove any empty lines that may have been left
        $content = preg_replace('/\n\n+/', "\n", $content);

        // Add the new value at the end
        $content = rtrim($content) . "\n" . $key . '=' . $value . "\n";

        // Write back to file
        file_put_contents($path, $content);

        \Log::info('Force updated environment variable', [
            'key' => $key,
            'value' => $value
        ]);
    }

    /**
     * Clear all Laravel caches
     */
    private function _clearAllCaches()
    {
        try {
            \Log::info('Clearing all caches');

            // Clear route cache
            try {
                \Artisan::call('route:clear');
                \Log::info('Route cache cleared');
            } catch (\Exception $e) {
                \Log::warning('Could not clear route cache: ' . $e->getMessage());
            }

            // Clear config cache
            try {
                \Artisan::call('config:clear');
                \Log::info('Config cache cleared');
            } catch (\Exception $e) {
                \Log::warning('Could not clear config cache: ' . $e->getMessage());
            }

            // Clear application cache
            try {
                \Artisan::call('cache:clear');
                \Log::info('Application cache cleared');
            } catch (\Exception $e) {
                \Log::warning('Could not clear application cache: ' . $e->getMessage());
            }

            // Clear view cache
            try {
                \Artisan::call('view:clear');
                \Log::info('View cache cleared');
            } catch (\Exception $e) {
                \Log::warning('Could not clear view cache: ' . $e->getMessage());
            }

            // Use optimize:clear if available
            if (function_exists('optimize_clear')) {
                optimize_clear();
                \Log::info('Optimization cleared using helper');
            }

            \Log::info('All caches cleared successfully');

        } catch (\Exception $e) {
            \Log::error('Failed to clear caches: ' . $e->getMessage());
            // Don't throw - cache clearing failure shouldn't stop installation
        }
    }

    /**
     * Validate user uniqueness after database tables are created
     */
    private function _validateUserUniqueness($userData)
    {
        try {
            \Log::info('Validating user uniqueness after database creation');

            // Check if username already exists
            $existingUsername = User::where('username', $userData['username'])->exists();
            if ($existingUsername) {
                throw new \Exception('Username "' . $userData['username'] . '" is already taken.');
            }

            // Check if email already exists
            $existingEmail = User::where('email', $userData['email'])->exists();
            if ($existingEmail) {
                throw new \Exception('Email address "' . $userData['email'] . '" is already registered.');
            }

            \Log::info('User uniqueness validation passed');

        } catch (\Exception $e) {
            \Log::error('User uniqueness validation failed: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Get professional error message for users
     */
    private function _getProfessionalErrorMessage(\Exception $ex)
    {
        $message = $ex->getMessage();

        // Database contains existing data
        if (strpos($message, 'Database contains existing data') !== false) {
            return 'Your database already contains installation data from a previous setup. Please check the "Force Installation" option below to overwrite the existing data and proceed with a fresh installation.';
        }

        // Database connection issues
        if (strpos($message, 'Connection refused') !== false ||
            strpos($message, 'Access denied') !== false) {
            return 'Database connection failed. Please go back to the previous step and verify your database credentials (host, port, username, password).';
        }

        // Migration issues
        if (strpos($message, 'migrate') !== false ||
            strpos($message, 'Migration') !== false) {
            return 'Database migration failed. This usually means there are conflicting tables or permission issues. Please try using "Force Installation" to reset the database completely.';
        }

        // Seeding issues
        if (strpos($message, 'seed') !== false ||
            strpos($message, 'Seeding') !== false) {
            return 'Database setup failed during data initialization. The database tables were created but default data could not be inserted. Please try "Force Installation" to reset and retry.';
        }

        // Unique constraint violations
        if (strpos($message, 'Duplicate entry') !== false ||
            strpos($message, 'unique') !== false ||
            strpos($message, 'already taken') !== false ||
            strpos($message, 'already registered') !== false) {
            return 'A user with this username or email already exists in the database. Please use "Force Installation" to overwrite existing data or choose different credentials.';
        }

        // Permission issues
        if (strpos($message, 'permission') !== false ||
            strpos($message, 'denied') !== false) {
            return 'Database permission error. Your database user does not have sufficient privileges to create tables or insert data. Please ensure your database user has CREATE, INSERT, UPDATE, DELETE, and DROP permissions.';
        }

        // Workspace creation issues
        if (strpos($message, 'workspace') !== false) {
            return 'Failed to create the default workspace for your admin account. This might be due to existing data conflicts. Please try "Force Installation" to reset the database.';
        }

        // Generic fallback with more helpful message
        return 'Installation failed due to an unexpected error: "' . $message . '". Please try using "Force Installation" to reset the database completely, or contact support if the issue persists.';
    }

    /**
     * Test database connection endpoint for AJAX calls
     */
    public function dbConnectionTest(Request $request)
    {
        $request->validate([
            'db_host' => "required",
            'db_port' => "required",
            'db_name' => "required",
            'db_user' => "required",
        ]);

        // Test database connection using the existing method
        $connectionResult = $this->_chekcDbConnection($request);

        return response()->json($connectionResult);
    }

    /**
     * Save purchase credentials from session to .env file and database
     */
    private function _savePurchaseCredentials()
    {
        try {
            $purchaseCode = session()->get(base64_decode('cHVyY2hhc2VfY29kZQ=='));
            $envatoUsername = session()->get(base64_decode('dXNlcm5hbWU='));

            if ($purchaseCode && $envatoUsername) {
                \Log::info('Saving purchase credentials to .env and database');

                // Save to .env file
                update_env('PURCHASE_KEY', $purchaseCode);
                update_env('ENVATO_USERNAME', $envatoUsername);

                // Save to database (settings table now exists after migration)
                $this->_saveLicenseToDatabase($purchaseCode, $envatoUsername);

                // Clear session data
                session()->forget(base64_decode('cHVyY2hhc2VfY29kZQ=='));
                session()->forget(base64_decode('dXNlcm5hbWU='));

                \Log::info('Purchase credentials saved successfully');
            } else {
                \Log::warning('No purchase credentials found in session');
            }
        } catch (\Exception $e) {
            \Log::error('Failed to save purchase credentials: ' . $e->getMessage());
            // Don't throw - this shouldn't stop installation
        }
    }

    /**
     * Save license data to database after installation
     */
    private function _saveLicenseToDatabase(string $purchaseCode, string $username)
    {
        try {
            \Log::info('Saving license data to database');

            $licenseToken = hash('sha384', $purchaseCode . $username . url('/') . config('app.key'));
            $domainFingerprint = hash('sha256', parse_url(url('/'), PHP_URL_HOST) . php_uname('n') . PHP_VERSION . config('app.key'));

            $settings = [
                'purchase_key' => $purchaseCode,
                'envato_username' => $username,
                'license_token' => $licenseToken,
                'license_verified_at' => \Carbon\Carbon::now()->toDateTimeString(),
                'license_status' => 'active',
                'domain_fingerprint' => $domainFingerprint,
                'verification_count' => 1
            ];

            foreach ($settings as $key => $value) {
                \App\Models\Core\Setting::updateOrCreate(
                    ['key' => $key],
                    ['value' => $value]
                );
            }

            \Log::info('License data saved to database successfully');
        } catch (\Exception $e) {
            \Log::error('Failed to save license data to database: ' . $e->getMessage());
            // Don't throw - this shouldn't stop installation
        }
    }
}
