<?php
/**
 * Middleware Class
 *
 * @todo        Gegebenenfalls muss noch eine Prüfung implementiert werden, um sicherzustellen,
 *              dass der aktuelle Mandant auf das Modul zugreifen darf.
 *
 * @version     1.0.$Revision:$
 * @version     SVN: $Id:$
 * @package     bplan-base/globals
 * @subpackage  Middlewares
 * @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\Http\Middleware;


use BplanBase\Globals\Models\Tenant;
use BplanBase\Globals\Models\User;
use BplanBase\Globals\Multitenancy\CoreWebTenantInitializer;
use BplanBase\Globals\Registries\ExtensionRegistry;
use BplanBase\Globals\Repositories\ModuleRepository;
use Closure;
use Illuminate\Http\Request;
use Spatie\Permission\PermissionRegistrar;


/**
 * Middleware Class
 *
 * @version     2.5.0 / 2026-06-08
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 */
class InitWebEnv
{


/* +++ TRAITS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ CLASS CONSTANTS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT MEMBERS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * @var Request
     */
    protected Request $_Request;


    /**
     * @var User
     */
    protected User $_User;


/* +++ CLASS MEMBERS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT METHODS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     *
     * @return      void
     *
     * @version     1.3.0 / 2026-06-06
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    protected function _determineModule(): void
    {
        /*
        **  Get the route prefix from the request object. */
        $routePrefix = $this->_Request->route()->getPrefix();

        if (empty($routePrefix)) {
            /*
            **  Fallback: wenn kein Präfix gesetzt ist aber die Route-URI mehrere Segmente hat
            **  (z. B. "tattile/targets"), wird das erste Segment als Präfix verwendet. */
            $uriSegments = explode('/', trim($this->_Request->route()->uri(), '/'));

            if (count($uriSegments) > 1) {
                $routePrefix = $uriSegments[0];
            }
        }
        if (empty($routePrefix)) {
            /*
            **  Reset module information in the registry. */
            \Registry::forget('env', true);
            \Registry::put('env.currentModule', null);

        } else {
            /*
            **  Determine the module via the route prefix. */
            $Module = ModuleRepository::getByRoutePrefix($routePrefix);

            if ($Module === null) {
                /*
                **  Kein direktes Modul gefunden. Prüfen ob der Präfix einer registrierten
                **  Extension gehört und ein Zielmodul auflösbar ist. */
                $targetModulePrefix = ExtensionRegistry::getTargetModule($routePrefix);

                $Module = $targetModulePrefix !== null
                    ? ModuleRepository::getByRoutePrefix($targetModulePrefix)
                    : null;
            }
            if ($Module === null) {
                /*
                **  Reset module information in the registry, if no proper module is found. */
                \Registry::forget('env', true);
                \Registry::put('env.currentModule', null);

            } else {
                /*
                **  Put the module information into the registry. */
                \Registry::put('env.currentModule', $Module->route_prefix);
                \Registry::put('env.module', $Module);
                \Registry::put('env.moduleName', $Module->package_name);
            }
        }
    } // _determineModule()


    /**
     *
     * @return      User
     *
     * @version     1.0.0 / 2026-02-17
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    protected function _getCurrentUser(): User
    {
        $User = auth()->user();

        if ($User !== null) {
            return $User;
        }
        return User::whereName('guest')->withoutTenancy()->first();

    } // _getCurrentUser()


    /**
     *
     * @param       Request $Request
     *
     * @return      void
     *
     * @version     1.1.0 / 2026-02-17
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    protected function _init(Request $Request)
    {
        $this->_Request = $Request;
        $this->_User = $this->_getCurrentUser();

    } // _init()


    /**
     *
     * @return      void
     *
     * @version     1.0.0 / 2026-02-17
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    protected function _initializeLocale(): void
    {
        $appLocale = $this->_Request->cookie('app_locale') ?: config('app.locale');

        app()->setLocale($appLocale);

        \Registry::put('appLocale', $appLocale);

    } // _initializeLocale()


    /**
     *
     * @return      void
     *
     * @version     1.0.1 / 2026-05-15
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    protected function _initializeTenant(): void
    {
        $finderClass = class_basename(config('multitenancy.tenant_finder'));

        if ($finderClass === 'CoreTenantFinder') {
            (new CoreWebTenantInitializer($this->_Request, $this->_User))->initialize();
        }
    } // _initializeTenant()


    /**
     *
     * @todo        Wird aktuell nicht verwendet. Es werden einfach immer nur Exceptions geworfen.
     *
     * @param       string $route
     *
     * @param       array $query
     *
     * @param       null|string $status
     *
     * @version     1.1.0 / 2026-02-17
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _performRedirect(string $route, array $query = [], null|string $status = null)
    {
        if ($route === 'login') {
            if ($status === null) {
                $status = __('globals::global.error.auto-logout');
            }
            return redirect('login')->with('status', $status);

        } elseif ($route === 'logout') {
            if ($status === null) {
                $status = __('globals::global.error.auto-logout');
            }
            auth()->guard('web')->logout();

            return $this->_performRedirect('login', $query, $status);
        }
        return redirect()->route($route, $query);

    } // _performRedirect()


    /**
     * Handle an incoming request.
     *
     * @param       Request $Request
     *
     * @param       Closure $next
     *
     * @return      void
     *
     * @version     1.7.0 / 2026-06-08
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function handle(Request $Request, Closure $next)
    {
        $this->_init($Request);

        $this->_initializeLocale();
        $this->_initializeTenant();
        $this->_determineModule();

        $Tenant = Tenant::current();

        if ($Tenant !== null) {
            app(PermissionRegistrar::class)->setPermissionsTeamId($Tenant->id);
        }
        return $next($Request);

    } // handle()


/* +++ CLASS METHODS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


} // class InitWebEnv {}
