<?php

namespace App\Http\Controllers;

use PDO;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use App\Events\EnvironmentSaved;
use App\Supports\DatabaseManager;
use App\Supports\PermissionsChecker;
use App\Supports\RequirementsChecker;
use App\Supports\InstalledFileManager;
use Illuminate\Support\Facades\Storage;

class InstallController extends Controller
{
    protected $requirements;
    protected $permissions;
    protected $databaseManager;
    protected $installedFileManager;

    /**
     * @param RequirementsChecker $checker
     */
    public function __construct(
        RequirementsChecker $requirementChecker,
        PermissionsChecker $permissionChecker,
        DatabaseManager $databaseManager,
        InstalledFileManager $installedFileManager)
    {
        $this->requirements = $requirementChecker;
        $this->permissions = $permissionChecker;
        $this->databaseManager = $databaseManager;
        $this->installedFileManager = $installedFileManager;
    }

    public function install()
    {
        return view('installer.index');
    }

    public function requirement()
    {
        $php = $this->requirements->checkPHPversion(
            config('installer.core.minPhpVersion')
        );

        $requirements = $this->requirements->check(
            config('installer.requirements')
        );

        return view('installer.requirement', compact('php', 'requirements'));
    }

    public function permission()
    {
        $permissions = $this->permissions->check(
            config('installer.permissions')
        );

        return view('installer.permission', compact('permissions'));
    }

    public function environment(Request $request)
    {
        return view('installer.environment');
    }

    public function saveEnvironment(Request $request)
    {
        $request->validate([
            'database_hostname' => 'required|string|max:50',
            'database_port' => 'required|numeric',
            'database_name' => 'required|string|max:50',
            'database_username' => 'required|string|max:50',
            'database_password' => '',
            'admin_email' => 'required|string',
            'admin_username' => 'required|string',
            'admin_password' => 'required|string',
        ]);

        $connection = $this->testConnectDB(
            $request->database_name,
            $request->database_username,
            $request->database_password
        );

        if (! $connection ) {
            return redirect()->back()
                    ->withInput()
                    ->withErrors(
                        'Could not connect to the database. Please check your configuration.'
                    );
        }

        if ($this->saveFileWizard( $request )) {
            return redirect()->route('install.installation');
        }

        return redirect()->back();
    }

    public function installation()
    {
        return view('installer.installation');
    }

    public function finish()
    {
        try {
            $this->databaseManager->migrate();
            $this->databaseManager->seed();
            $this->installedFileManager->create();
            $this->envSessionAppend();
        } catch (\Exception $e) {
            return redirect()
                    ->route('install.environment')
                    ->withErrors($e->getMessage());
        }

        return view('installer.finish');
    }

    private function saveFileWizard(Request $request)
    {
        $envFileData =
        'APP_NAME=Mopie'."\n".
        'APP_ENV=production'."\n".
        'APP_KEY='.'base64:'.base64_encode(Str::random(32))."\n".
        'APP_DEBUG=false'."\n".
        'APP_URL='.$this->baseUrl()."\n\n".

        'DB_CONNECTION=mysql'."\n".
        'DB_HOST='.$request->database_hostname."\n".
        'DB_PORT='.$request->database_port."\n".
        'DB_DATABASE='.$request->database_name."\n".
        'DB_USERNAME='.$request->database_username."\n".
        'DB_PASSWORD='.$request->database_password."\n\n".

        'CACHE_DRIVER=database'."\n\n".

        'ADMIN_EMAIL='.$request->admin_email."\n".
        'ADMIN_USERNAME='.$request->admin_username."\n".
        'ADMIN_PASSWORD='.$request->admin_password."\n";

        try {
            Storage::disk('env')->put('.env', $envFileData);
            event(new EnvironmentSaved($request));
            return true;
        } catch (\Throwable $th) {
            return false;
        }
    }

    private function testConnectDB($name, $root, $pass)
    {
        try {
            $conn = new PDO('mysql:host=localhost; dbname='.$name,$root, $pass);
            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $conn;
		} catch(\Exception $e) {
			return false;
		}
    }

    private function baseUrl()
    {
        return Url::to('/');
    }

    private function envSessionAppend()
    {
        $sessionAppend = 'SESSION_DRIVER=database'."\n";
        try {
            Storage::disk('env')->append('.env', $sessionAppend);
            return true;
        } catch (\Throwable $th) {
            return false;
        }
    }
}
