<?php

namespace App\Provisioning\Steps\Customer;

use App\Models\ProvisioningRun;
use App\Notifications\CloudReady;
use App\Provisioning\StepResult;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Notification;

class CompleteProvisioning extends CustomerStep
{
    public function key(): string
    {
        return 'complete_provisioning';
    }

    public function maxDuration(): int
    {
        return 60;
    }

    public function execute(ProvisioningRun $run): StepResult
    {
        $order = $this->order($run);
        $instance = $this->instance($run);

        // Do all fallible work FIRST, so a failure can't leave the instance
        // active. Onboarding tasks (idempotent) + credential delivery.
        foreach (['invite_users', 'upload_logo', 'connect_desktop', 'explore_apps'] as $key) {
            $instance->onboardingTasks()->firstOrCreate(['key' => $key], ['done' => false]);
        }

        $encrypted = $run->context('admin_password');
        if ($encrypted !== null && ! $this->hasResource($run, 'credentials_sent')) {
            // Move the password onto the instance (encrypted cast — see
            // Instance::casts()) so it survives until the customer
            // acknowledges it on the dashboard. Decrypted here only to
            // re-encrypt it under that cast; it never reaches the mail.
            $instance->update(['admin_password' => Crypt::decryptString($encrypted)]);

            Notification::route('mail', $order->customer->email)->notify(
                new CloudReady($instance),
            );
            // Record delivery so a retry after a crash doesn't re-send.
            $this->recordResource($run, $instance->host, 'credentials_sent', (string) $instance->nc_admin_ref);
        }

        // Always scrub once delivery is recorded — even if a crash interrupted a
        // previous attempt between recording and scrubbing.
        if ($this->hasResource($run, 'credentials_sent')) {
            $run->forgetContext('admin_password');
        }

        // Activate LAST — only once everything above succeeded.
        $instance->update(['status' => 'active']);
        $order->update(['status' => 'active']);

        return StepResult::advance();
    }
}
