<?php

namespace App\Support;

use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class EnvFileEditor
{
    public function ensureExists(): void
    {
        if (File::exists(base_path('.env'))) {
            return;
        }

        File::copy(base_path('.env.example'), base_path('.env'));
    }

    public function ensureAppKey(): string
    {
        $this->ensureExists();

        $key = (string) config('app.key');

        if (filled($key)) {
            return $key;
        }

        $key = 'base64:'.base64_encode(random_bytes(32));
        $this->set(['APP_KEY' => $key]);
        config(['app.key' => $key]);

        return $key;
    }

    /**
     * @param  array<string, mixed>  $values
     */
    public function set(array $values): void
    {
        $this->ensureExists();

        $path = base_path('.env');
        $contents = File::get($path);

        foreach ($values as $key => $value) {
            $formatted = $this->formatValue($value);
            $pattern = "/^{$key}=.*$/m";

            if (preg_match($pattern, $contents) === 1) {
                $contents = preg_replace($pattern, "{$key}={$formatted}", $contents) ?? $contents;
            } else {
                $contents = rtrim($contents).PHP_EOL."{$key}={$formatted}".PHP_EOL;
            }
        }

        File::put($path, $contents);
    }

    private function formatValue(mixed $value): string
    {
        if (is_bool($value)) {
            return $value ? 'true' : 'false';
        }

        if ($value === null) {
            return '';
        }

        $value = (string) $value;

        if ($value === '') {
            return '';
        }

        if (preg_match('/[\s#="$]/', $value) === 1) {
            return '"'.Str::replace('"', '\"', $value).'"';
        }

        return $value;
    }
}
