<?php

declare(strict_types=1);

namespace App\Framework\Http\Session;

use App\Framework\Http\Session\ValueObjects\FormData;

/**
 * This class provides functionality to store, retrieve, and manage form data
 * in a session-based storage.
 */
final readonly class FormDataStorage
{
    public function __construct(
        private Session $session
    ) {
    }

    public function store(string $formId, array $data): void
    {
        $formData = FormData::create($data, ['stored_at' => time()]);

        $this->session->updateSessionData(function ($sessionData) use ($formId, $formData) {
            return $sessionData->withFormData(
                $sessionData->formData->with($formId, $formData)
            );
        });
    }

    public function get(string $formId): array
    {
        $formData = $this->session->getSessionData(true)->formData->get($formId); // Include marked for deletion

        return $formData ? $formData->fields : [];
    }

    /**
     * Gibt Form-Daten zurück UND markiert sie zum Löschen (Flash-Verhalten)
     *
     * @param string $formId Formular-ID
     * @return array<string, mixed> Form-Daten
     */
    public function getAndFlash(string $formId): array
    {
        $sessionData = $this->session->getSessionData(true); // Include marked for deletion
        $formData = $sessionData->formData->get($formId);
        $data = $formData ? $formData->fields : [];

        // Mark for deletion (deferred flash behavior)
        if (! empty($data)) {
            $this->session->flashManager->mark(SessionKey::FORM_DATA->value, $formId);
        }

        return $data;
    }

    public function getField(string $formId, string $field, $default = null)
    {
        $data = $this->get($formId);

        return $data[$field] ?? $default;
    }

    /**
     * Gibt ein spezifisches Feld zurück UND markiert das Formular zum Löschen
     *
     * @param string $formId Formular-ID
     * @param string $field Feldname
     * @param mixed $default Standard-Wert falls Feld nicht existiert
     * @return mixed Feldwert oder Standard-Wert
     */
    public function getFieldAndFlash(string $formId, string $field, $default = null)
    {
        $data = $this->getAndFlash($formId);

        return $data[$field] ?? $default;
    }

    public function has(string $formId): bool
    {
        return $this->session->getSessionData()->formData->has($formId);
    }

    public function clear(string $formId): void
    {
        $this->session->updateSessionData(function ($sessionData) use ($formId) {
            return $sessionData->withFormData(
                $sessionData->formData->without($formId)
            );
        });
    }

    public function clearAll(): void
    {
        $this->session->updateSessionData(function ($sessionData) {
            return $sessionData->withFormData(
                new \App\Framework\Http\Session\ValueObjects\FormDataCollection([])
            );
        });
    }
}
