<?php

declare(strict_types=1);

namespace App\Framework\Http\Session;

use App\Framework\Http\Cookies\SameSite;

final readonly class SessionCookieConfig
{
    public function __construct(
        public string $path = '/',
        public ?string $domain = null,
        public bool $secure = true,
        public bool $httpOnly = true,
        public SameSite $sameSite = SameSite::Lax,
        public int $lifetime = 0, // 0 = session cookie (browser close)
        public ?string $prefix = null, // Cookie prefix for additional security
    ) {
    }

    /**
     * Erstellt eine Config aus einem Array (für Backward Compatibility)
     */
    public static function fromArray(array $config): self
    {
        return new self(
            path: $config['path'] ?? '/',
            domain: $config['domain'] ?? null,
            secure: $config['secure'] ?? true,
            httpOnly: $config['httpOnly'] ?? true,
            sameSite: self::parseSameSite($config['sameSite'] ?? 'lax'),
            lifetime: $config['lifetime'] ?? 0,
            prefix: $config['prefix'] ?? null,
        );
    }

    /**
     * Konvertiert zu Array (für Legacy-Code)
     */
    public function toArray(): array
    {
        return [
            'path' => $this->path,
            'domain' => $this->domain,
            'secure' => $this->secure,
            'httpOnly' => $this->httpOnly,
            'sameSite' => $this->sameSite->value,
            'lifetime' => $this->lifetime,
            'prefix' => $this->prefix,
        ];
    }

    /**
     * Factory-Methode für Development-Umgebung
     */
    public static function forDevelopment(): self
    {
        return new self(
            secure: false, // HTTP in development
            sameSite: SameSite::Lax,
        );
    }

    /**
     * Factory-Methode für Production-Umgebung
     */
    public static function forProduction(): self
    {
        return new self(
            secure: true,
            httpOnly: true,
            sameSite: SameSite::Strict,
            prefix: '__Secure-', // Cookie-Prefix für zusätzliche Sicherheit
        );
    }

    /**
     * Factory-Methode für API-Sessions
     */
    public static function forApi(): self
    {
        return new self(
            httpOnly: true,
            sameSite: SameSite::None, // Für Cross-Origin Requests
            secure: true,
            lifetime: 3600, // 1 Stunde
        );
    }

    private static function parseSameSite(string $value): SameSite
    {
        return match (strtolower($value)) {
            'strict' => SameSite::Strict,
            'lax' => SameSite::Lax,
            'none' => SameSite::None,
            default => SameSite::Lax,
        };
    }

    /**
     * Validiert die Konfiguration
     */
    public function validate(): void
    {
        // SameSite=None erfordert Secure
        if ($this->sameSite === SameSite::None && ! $this->secure) {
            throw new \InvalidArgumentException(
                'SameSite=None requires the Secure attribute'
            );
        }

        // __Secure- Prefix erfordert Secure
        if ($this->prefix === '__Secure-' && ! $this->secure) {
            throw new \InvalidArgumentException(
                '__Secure- prefix requires the Secure attribute'
            );
        }

        // __Host- Prefix hat spezielle Anforderungen
        if ($this->prefix === '__Host-') {
            if (! $this->secure || $this->domain !== null || $this->path !== '/') {
                throw new \InvalidArgumentException(
                    '__Host- prefix requires Secure, no Domain, and Path=/'
                );
            }
        }
    }

    /**
     * Gibt den vollständigen Cookie-Namen mit Prefix zurück
     */
    public function getCookieName(string $baseName): string
    {
        return ($this->prefix ?? '') . $baseName;
    }
}
