<?php

namespace apexl\Io\modules\user;

use apexl\Io\enums\HttpMethod;
use apexl\Io\includes\Controller;
use apexl\Io\includes\RouteManager;
use apexl\Io\middleware\permission\permissionController;
use apexl\Io\middleware\session\sessionMiddleware;
use apexl\Io\modules\email\services\TemplateService;
use apexl\Io\modules\system\interfaces\ProvidesMiddlewareInterface;
use apexl\Io\modules\system\interfaces\ProvidesRoutesInterface;
use apexl\Io\modules\user\classes\userManagedApiModule;
use apexl\Io\modules\user\controllers\rolesController;
use apexl\Io\modules\user\controllers\userController;
use apexl\Io\modules\user\entities\roleEntity;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\enums\permissions\Role;
use apexl\Io\modules\user\enums\permissions\User;
use apexl\Io\modules\user\hooks\RegisterModulePermissions;
use apexl\Io\modules\user\hooks\RegisterRolePermissions;
use apexl\Io\modules\user\hooks\SendNewUserNotification;
use apexl\Io\modules\user\interfaces\ProvidesPermissionsInterface;
use apexl\Io\modules\user\services\Permissions;
use apexl\Io\services\InstallChecker;
use app\vendor\apexl\io\src\Io\interfaces\ProvidesHooksInterface;
use Slim\App;

/**
 * Base module file, provides required methods to register things like routes and middleware.
 * Class installModule
 * @package apexl\Io\modules\install
 */
class userModule extends userManagedApiModule implements ProvidesHooksInterface, ProvidesPermissionsInterface, ProvidesMiddlewareInterface, ProvidesRoutesInterface
{
    public function __construct(
        private TemplateService $templateService,
        InstallChecker $installChecker,
    ) {
        parent::__construct($installChecker);
    }

    public function initialise(): void
    {
        parent::initialise();
        $this->templateService->locations->add(sprintf('%s/templates/email', __DIR__));
    }

    public function routes(RouteManager $routeManager): void
    {
        $this->addGlobalRoutes($routeManager);
        //@route VERB /api/v{VERSION}/user/user
        $this->addProtectedEntityRoutes($routeManager, new userEntity(), [
            'get' => [Controller::class . ':get', User::VIEW],
            'put' => [userController::class . ':register', User::UPDATE_SELF],
            'post' => [userController::class . ':register', User::UPDATE_SELF],
            'delete' => [Controller::class . ':delete', User::DELETE],
        ]);

        //@route VERB /api/v{VERSION}/user/role
        $this->addProtectedEntityRoutes($routeManager, new roleEntity(), [
            'get' => [rolesController::class . ':getRoles', Role::VIEW],
            'put' => [rolesController::class . ':createUpdate', Role::CREATE],
            'post' => [rolesController::class . ':createUpdate', Role::CREATE],
            'delete' => [rolesController::class . ':delete', Role::DELETE],
        ]);
    }

    protected function addGlobalRoutes(RouteManager $routeManager)
    {
        //@route GET /api/v{VERSION}/user/actions/logout
        $this->addActionRoute(
            $routeManager,
            HttpMethod::GET,
            'user.logout',
            'logout',
            userController::class . ':logout'
        );
        //@route GET /api/v{VERSION}/user/actions/login
        $this->addActionRoute($routeManager, HttpMethod::POST, 'user.login', 'login', userController::class . ':login');
        //@route GET /api/v{VERSION}/user/actions/login/nfc
        $this->addActionRoute(
            $routeManager,
            HttpMethod::POST,
            'user.login.nfc',
            'login/nfc',
            userController::class . ':loginByKey'
        );
        //@route GET /api/v{VERSION}/user/actions/forgot-password
        $this->addActionRoute(
            $routeManager,
            HttpMethod::POST,
            'user.forgot-password',
            'forgot-password',
            userController::class . ':forgotPassword'
        );
        //@route GET /api/v{VERSION}/user/data/forgot-password/h/{hash}
        $this->addDataRoute(
            $routeManager,
            HttpMethod::GET,
            'user.forgot-password.hash',
            'forgot-password/h/{hash}',
            userController::class . ':forgotPasswordWithLink'
        );
        $this->addActionRoute(
            $routeManager,
            HttpMethod::POST,
            'user.refresh',
            'refresh',
            userController::class . ':refresh'
        );
        $this->addActionRoute(
            $routeManager,
            HttpMethod::POST,
            'user.loginAsUser',
            'loginAsUser',
            userController::class . ':loginAsUser',
        );
        $this->addActionRoute(
            $routeManager,
            HttpMethod::POST,
            'user.createNote',
            'create-note',
            userNoteController::class . ':createUserNote',
        );
        $this->addProtectedDataRoute(
            $routeManager,
            HttpMethod::GET,
            'user-note.data.basic',
            'user-note/data/basic/{userId}',
            userNoteController::class . ':userNoteListTableDataBasic',
            User::UPDATE,
        );
        $this->addActionRoute(
            $routeManager,
            HttpMethod::POST,
            'user.resetPassword',
            'reset-password',
            userController::class . ':resetPassword',
            'AllowAll',
        );
    }

    /**
     * Function to add the middleware required by this module.
     * NOTE - Slim v4 is LIFO so the middleware added last is loaded first.
     */
    public function middleware(App $application): void
    {
        $application->add(permissionController::class);
        $application->add(sessionMiddleware::class);
    }

    public function permissions(Permissions $permissions): void
    {
        $permissions->registerPermission(User::VIEW, 'View Users', 'Users');
        $permissions->registerPermission(User::CREATE, 'Create Users', 'Users');
        $permissions->registerPermission(User::UPDATE, 'Update Users', 'Users');
        $permissions->registerPermission(User::UPDATE_SELF, 'Update Self', 'Users');
        $permissions->registerPermission(User::CHANGE_ACTIVE_STATE, 'Change Active State', 'Users');
        $permissions->registerPermission(User::DELETE, 'Delete Users', 'Users');
        $permissions->registerPermission(User::CAN_REGISTER, 'Can Register (For Anon Users)', 'Users');
        $permissions->registerPermission(User::MANAGE, 'Manage All User Accounts');

        $permissions->registerPermission(Role::SET, 'Can Set User Roles', 'Users');
        $permissions->registerPermission(Role::VIEW, 'View Roles', 'Roles');
        $permissions->registerPermission(Role::CREATE, 'Create Roles', 'Roles');
        $permissions->registerPermission(Role::UPDATE, 'Update Roles', 'Roles');
        $permissions->registerPermission(Role::DELETE, 'Delete Roles', 'Roles');

    }

    public function hooks(): array
    {
        return [
            RegisterRolePermissions::class,
            SendNewUserNotification::class,
            RegisterModulePermissions::class,
        ];
    }
}
