<?php
/**
 * UserAccessLevel Enum Class
 *
 * @version     1.0.$Revision:$
 * @version     SVN: $Id:$
 * @package     bplan-base/globals
 * @subpackage  Enums
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 * @copyright   Copyright (C) 2025, 2026 bplan-solutions GmbH & Co. KG <https://www.bplan-solutions.de/>
 * /Δ\
 */

namespace BplanBase\Globals\Enums;


/**
 * UserAccessLevel Enum Class
 *
 * @version     1.4.0 / 2026-02-17
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 */
enum UserAccessLevel: int
{


/* +++ CASES +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */


    case God           = 100;

    case Developer     = 99;

    case System        = 98;

    case SystemTester  = 90;

    case Maintainer    = 80;

    case SystemAdmin   = 70;

    case SystemManager = 69;

    case Tester        = 50;

    /*
    **  Nur die nachfolgenden Level dürfen bei Usern auf Mandantenebene
    **  eingesetzt werden. */

    // case SuperUser     = 45;

    case Admin         = 40;

    case Manager       = 39;

    case Staff         = 20;

    case User          = 1;

    case Guest         = 0;


/* +++ STATIC METHODS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * Liefert den Schlüssel zum übergebenen Wert
     *
     * @param       int $value
     *
     * @return      null|string
     *
     * @version     1.1.0 / 2024-08-01
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public static function getName(int $value): null|string
    {
        if (UserAccessLevel::tryFrom($value) === null) {
            return null;
        }
        return UserAccessLevel::from($value)->name;

    } // getName()


    /**
     * Liefert eine Liste von gültigen AccessLevels
     *
     * Gültige AccessLevel sind die Level deren Wert kleiner oder gleich dem übergebenen Level sind.
     *
     * @param       string|null $baseAccessLevel
     *              Der AccessLevel, der als Basis für die Liste verwendet werden soll.
     *              Wenn dieser Parameter nicht angegeben ist, dann wird der Inhalt des Ergebnisses
     *              auf Basis des AccessLevels der angemeldeten Benutzers ermittelt.
     *
     * @return      array
     *
     * @version     2.3.0 / 2026-02-17
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public static function getValidAccessLevels(string|null $baseAccessLevel = null): array
    {
        /*
        **  Alle AccessLevel ermitteln und in eine filterbare Form bringen. */
        $cases = UserAccessLevel::cases();

        $accessLevels = array_combine(array_column($cases, 'value'), array_column($cases, 'name'));

        if ($baseAccessLevel === null) {
            /*
            **  AccessLevel des aktuell angemeldeten Benutzers ermitteln. */
            $baseAccessLevel = \Registry::get('core.userAccessLevel');
        }
        /*
        **  Prüfen ob der AccessLevel gültig ist. */
        if (!in_array($baseAccessLevel, $accessLevels)) {
            return [];
        }
        $baseAccessLevelValue = self::getValue($baseAccessLevel);
        /*
        **  God-Level entfernen. Dieser Level ist nie auswählbar. */
        unset($accessLevels[UserAccessLevel::God->value]);
        /*
        **  AccessLevel herausfiltern die höher sind als der übergebene/ermittelte AccessLevel. */
        return array_filter($accessLevels, function ($key) use ($baseAccessLevelValue) {
            return $key <= $baseAccessLevelValue;

        }, ARRAY_FILTER_USE_KEY);

    } // getValidAccessLevels()


    /**
     * Liefert den Wert zum übergebenen Schlüssel
     *
     * @param       string $name
     *
     * @return      int
     *
     * @version     2.0.0 / 2025-04-18
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public static function getValue(null|string $name): int
    {
        if ($name === null || defined('self::'.$name) === false) {
            return self::Guest->value;
        }
        return (int) constant('self::'.$name)->value;

    } // getValue()


} // enum UserAccessLevel {}
