<?php

declare(strict_types=1);

namespace App\Domain\Resource\Listeners;

use App\Domain\Account\Events\AccountProvisioned;
use App\Domain\Resource\Services\CgroupManager;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;

/**
 * Yeni hesap provisioned olduğunda cgroup limit'lerini hemen uygula.
 *
 * Account creation flow:
 *   1. AccountController::store → DB satırı + sysapi 'user-add'
 *   2. AccountProvisioned event fırlatılır
 *   3. Bu listener cgroup-apply ile systemd slice'a limit yazar
 *   4. Aksi halde hesap provisioned olur fakat cgroup default'larıyla
 *      (limit yok) çalışır — production'da resource isolation kırılır.
 *
 * ShouldQueue: backups queue'sunda async — provisioning request'i blocklamasın.
 * Hata olursa log'lanır; account creation'ı geri sarmaz (cgroup yokken account
 * yine çalışır, sadece limit uygulanmaz — admin manuel re-apply edebilir).
 */
class ApplyCgroupsOnAccountProvisioned implements ShouldQueue
{
    public string $queue = 'provisioning';
    public int $tries = 2;
    public int $timeout = 60;

    public function __construct(private readonly CgroupManager $cgroups) {}

    public function handle(AccountProvisioned $event): void
    {
        try {
            $result = $this->cgroups->applyTo($event->account);

            Log::info('cgroup.applied_on_provisioning', [
                'account_id' => $event->account->id,
                'username' => $event->account->username,
                'slice' => $result['slice'] ?? null,
            ]);
        } catch (\Throwable $e) {
            Log::warning('cgroup.apply_on_provisioning_failed', [
                'account_id' => $event->account->id,
                'username' => $event->account->username,
                'error' => $e->getMessage(),
            ]);
            // İstemiyoruz exception'ı yutmak; queue retry mekanizmasının çalışmasını sağla.
            throw $e;
        }
    }
}
