<?php

namespace App\Services;

use App\Services\TenantBootstrap\RecipeRegistry;
use App\Services\TenantBootstrap\Support\TenantBootstrapLogger;
use Illuminate\Support\Facades\DB;

class TenantBootstrapper
{
    public function __construct(private RecipeRegistry $registry) {}

    public function bootstrap(int $tenantId, string $recipe = 'STANDARD'): void
    {
        $logger = new TenantBootstrapLogger;
        $steps = $this->registry->steps($recipe);
        $ver = $this->registry->version($recipe);

        DB::transaction(function () use ($tenantId, $recipe, $steps, $ver, $logger) {
            $runId = DB::table('tenant_bootstrap_runs')->insertGetId([
                'tenant_id' => $tenantId, 'recipe' => $recipe, 'recipe_version' => $ver,
                'status' => 'RUNNING', 'steps' => json_encode([]), 'log' => json_encode([]),
                'created_at' => now(), 'updated_at' => now(),
            ]);

            $done = [];
            try {
                foreach ($steps as $step) {
                    /** @var \App\Services\TenantBootstrap\Contracts\TenantBootstrapStep $step */
                    $logger->info('start step', ['key' => $step->key()]);
                    $step->run($tenantId);
                    $done[] = $step->key();
                    $logger->info('end step', ['key' => $step->key()]);
                    DB::table('tenant_bootstrap_runs')->where('id', $runId)->update([
                        'steps' => json_encode($done),
                        'log' => json_encode($logger->dump(), JSON_UNESCAPED_UNICODE),
                        'updated_at' => now(),
                    ]);
                }
                DB::table('tenant_bootstrap_runs')->where('id', $runId)->update([
                    'status' => 'SUCCESS',
                    'log' => json_encode($logger->dump(), JSON_UNESCAPED_UNICODE),
                    'updated_at' => now(),
                ]);
            } catch (\Throwable $e) {
                $logger->error('step failed', ['exception' => $e->getMessage()]);
                DB::table('tenant_bootstrap_runs')->where('id', $runId)->update([
                    'status' => 'FAILED',
                    'log' => json_encode($logger->dump(), JSON_UNESCAPED_UNICODE),
                    'updated_at' => now(),
                ]);
                throw $e;
            }
        });
    }
}
