<?php

namespace App\Services\Installer;

use App\DTOs\Installer\WizardStateData;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\File;

class WizardSessionStore
{
    public function get(): WizardStateData
    {
        $path = $this->path();

        if (! File::exists($path)) {
            return new WizardStateData;
        }

        try {
            $data = json_decode(Crypt::decryptString(File::get($path)), true, 512, JSON_THROW_ON_ERROR);

            return WizardStateData::fromArray(is_array($data) ? $data : []);
        } catch (DecryptException|\JsonException|\Throwable) {
            $this->clear();

            return new WizardStateData;
        }
    }

    public function put(WizardStateData $state): void
    {
        $directory = dirname($this->path());

        if (! File::isDirectory($directory)) {
            File::makeDirectory($directory, 0755, true);
        }

        File::put(
            $this->path(),
            Crypt::encryptString(json_encode($state->toArray(), JSON_THROW_ON_ERROR))
        );
    }

    public function merge(array $attributes): WizardStateData
    {
        $state = $this->get()->with($attributes);
        $this->put($state);

        return $state;
    }

    public function clear(): void
    {
        if (File::exists($this->path())) {
            File::delete($this->path());
        }
    }

    private function path(): string
    {
        return storage_path('app/'.config('installer.wizard_state_file', 'installer/wizard.dat'));
    }
}
