<?php

namespace App\Domains\Event\Actions\SetEventAddons;

use App\ValueObjects\Amount;
use Illuminate\Support\Str;

class SetEventAddonsCommand
{
    public function __construct(private SetEventAddonsRequest $request)
    {
    }

    public function execute(): SetEventAddonsResponse
    {
        $response = new SetEventAddonsResponse();

        $this->request->event->addons = $this->normalize($this->request->addons);
        $this->request->event->save();

        $response->success = true;
        return $response;
    }

    /**
     * Normalisiert die rohe Addon-Definition: trimmt Titel/Beschreibung, parst den Preis (≥ 0), erzwingt den
     * Titel als Pflichtfeld und generiert stabile Keys (Bestandsschutz für bereits gespeicherte Buchungen).
     *
     * @param array<int, array<string, mixed>> $addons
     * @return array<int, array{key: string, title: string, description: string, price: float, flat: bool}>
     */
    private function normalize(array $addons): array
    {
        $normalized = [];
        $usedKeys = [];

        foreach ($addons as $addon) {
            $title = trim((string)($addon['title'] ?? ''));
            if ($title === '') {
                continue;
            }

            $price = Amount::fromString((string)($addon['price'] ?? '0'))->getAmount();
            if ($price < 0) {
                $price = 0.0;
            }

            $key = $this->uniqueSlug((string)($addon['key'] ?? ''), $title, $usedKeys);
            $usedKeys[] = $key;

            $normalized[] = [
                'key' => $key,
                'title' => $title,
                'description' => trim((string)($addon['description'] ?? '')),
                'price' => round($price, 2),
                'flat' => (bool)($addon['flat'] ?? false),
            ];
        }

        return $normalized;
    }

    /**
     * Liefert einen eindeutigen Slug: bevorzugt den bestehenden Wert, sonst aus dem Titel abgeleitet;
     * Kollisionen werden durchnummeriert.
     *
     * @param array<int, string> $used
     */
    private function uniqueSlug(string $existing, string $title, array $used): string
    {
        $base = $existing !== '' ? $existing : Str::slug($title);
        if ($base === '') {
            $base = 'addon';
        }

        $candidate = $base;
        $suffix = 2;
        while (in_array($candidate, $used, true)) {
            $candidate = $base . '-' . $suffix;
            $suffix++;
        }

        return $candidate;
    }
}
