<?php

declare(strict_types=1);

namespace Builder\Core\Foundation\Commands;

use Illuminate\Console\Command;

abstract class MakeBuilderFileCommand extends Command
{
    abstract protected function stubName(): string;

    abstract protected function outputSubdirectory(): string;

    abstract protected function packageStubsPath(): string;

    /** @return array<string, string> */
    abstract protected function buildReplacements(string $className): array;

    public function handle(): int
    {
        /** @var string $className */
        $className = $this->argument('name');
        $outputPath = app_path("Builder/{$this->outputSubdirectory()}/{$className}.php");

        if (file_exists($outputPath) && ! $this->option('force')) {
            $this->components->error("{$className} already exists.");

            return self::FAILURE;
        }

        $stub = $this->resolveStub();

        foreach ($this->buildReplacements($className) as $placeholder => $value) {
            $stub = str_replace("{{ {$placeholder} }}", $value, $stub);
        }

        $directory = dirname($outputPath);

        if (! is_dir($directory)) {
            mkdir($directory, 0755, true);
        }

        file_put_contents($outputPath, $stub);

        $this->components->info("{$className} created successfully.");
        $this->components->bulletList([
            app()->basePath("app/Builder/{$this->outputSubdirectory()}/{$className}.php"),
        ]);

        return self::SUCCESS;
    }

    private function resolveStub(): string
    {
        $published = base_path("stubs/builder/{$this->stubName()}.stub");

        if (file_exists($published)) {
            return (string) file_get_contents($published);
        }

        return (string) file_get_contents($this->packageStubsPath()."/{$this->stubName()}.stub");
    }
}
