<?php

declare(strict_types=1);

namespace App\Core;

final class Session
{
    public static function start(): void
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
    }

    /**
     * Supports normal keys: user
     * Supports dot keys: user.name, user.hospital
     */
    public static function get(string $key, $default = null)
    {
        if ($key === '') {
            return $default;
        }

        if (array_key_exists($key, $_SESSION)) {
            return $_SESSION[$key];
        }

        if (strpos($key, '.') === false) {
            return $default;
        }

        $value = $_SESSION;
        foreach (explode('.', $key) as $part) {
            if (!is_array($value) || !array_key_exists($part, $value)) {
                return $default;
            }
            $value = $value[$part];
        }

        return $value;
    }

    /**
     * Supports normal keys and dot keys.
     * Example: Session::put('user.name', 'admin')
     */
    public static function put(string $key, $value): void
    {
        if (strpos($key, '.') === false) {
            $_SESSION[$key] = $value;
            return;
        }

        $parts = explode('.', $key);
        $target =& $_SESSION;
        foreach ($parts as $index => $part) {
            if ($index === count($parts) - 1) {
                $target[$part] = $value;
                return;
            }
            if (!isset($target[$part]) || !is_array($target[$part])) {
                $target[$part] = [];
            }
            $target =& $target[$part];
        }
    }

    public static function forget(string $key): void
    {
        if (strpos($key, '.') === false) {
            unset($_SESSION[$key]);
            return;
        }

        $parts = explode('.', $key);
        $last = array_pop($parts);
        $target =& $_SESSION;
        foreach ($parts as $part) {
            if (!isset($target[$part]) || !is_array($target[$part])) {
                return;
            }
            $target =& $target[$part];
        }
        unset($target[$last]);
    }

    public static function regenerate(): void
    {
        if (session_status() === PHP_SESSION_ACTIVE) {
            session_regenerate_id(true);
        }
    }

    public static function save(): void
    {
        if (session_status() === PHP_SESSION_ACTIVE) {
            session_write_close();
        }
    }

    public static function destroy(): void
    {
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(
                session_name(),
                '',
                time() - 42000,
                $params['path'],
                $params['domain'],
                (bool) $params['secure'],
                (bool) $params['httponly']
            );
        }
        session_destroy();
    }

    public static function flash(string $key, ?string $value = null): ?string
    {
        if ($value !== null) {
            $_SESSION['_flash'][$key] = $value;
            return null;
        }

        $message = $_SESSION['_flash'][$key] ?? null;
        unset($_SESSION['_flash'][$key]);
        return $message;
    }
}
