<?php

declare(strict_types=1);

namespace App\Modules\Administration\Controllers;

use App\Controllers\Controller;
use App\Modules\Administration\Services\AuthenticationService;
use App\Modules\Administration\Services\UserService;
use RuntimeException;
use System\Http\Request;
use System\View\View;
use App\Modules\Administration\Services\AuthorizationService;
final class UserController extends Controller
{
public function __construct(
    private AuthenticationService $authentication,
    private AuthorizationService $authorization,
    private UserService $userService,
    private Request $request,
    View $view
) {
    parent::__construct($view);
}
private function requirePermission(
    string $permission
): void {
    if (!$this->authorization->can($permission)) {

        header(
            'Location: /public/403'
        );

        exit;
    }
}
    private function protect(): void
    {
        if (!$this->authentication->check()) {

            header('Location: /public/login');

            exit;
        }
    }

    public function index(): void
    {
        $this->protect();
// index()
$this->requirePermission('users.view');

// create()
$this->requirePermission('users.create');

// store()
$this->requirePermission('users.create');

// edit()
$this->requirePermission('users.edit');

// update()
$this->requirePermission('users.edit');

// toggleStatus()
$this->requirePermission('users.status');

// resetPasswordForm()
$this->requirePermission('users.edit');

// resetPassword()
$this->requirePermission('users.edit');
        $this->render(
            'users/index',
            [
                'title' => 'User Management',
                'users' => $this->userService->all(),
                'created' => $this->request->input('created'),
                'updated' => $this->request->input('updated'),
                'statusChanged' => $this->request->input(
                    'status_changed'
                ),
                'passwordReset' => $this->request->input(
                    'password_reset'
                ),
                'error' => $this->request->input('error')
            ]
        );
    }

    public function create(): void
    {
        $this->protect();

        $this->render(
            'users/create',
            [
                'title' => 'Create User',
                'roles' => $this->userService->roles()
            ]
        );
    }

    public function store(): void
    {
        $this->protect();

        try {

            $this->userService->create(
                $this->request->all()
            );

            header(
                'Location: /public/users?created=1'
            );

            exit;

        } catch (\Throwable $exception) {

            $this->render(
                'users/create',
                [
                    'title' => 'Create User',
                    'roles' => $this->userService->roles(),
                    'error' => $exception->getMessage(),
                    'old' => $this->request->all()
                ]
            );
        }
    }

    public function edit(): void
    {
        $this->protect();

        $id = (int) $this->request->input(
            'id',
            0
        );

        $user = $this->userService->find($id);

        if ($user === null) {
            throw new RuntimeException(
                'User not found.'
            );
        }

        $this->render(
            'users/edit',
            [
                'title' => 'Edit User',
                'user' => $user,
                'roles' => $this->userService->roles(),
                'userRoleId' =>
                    $this->userService->userRoleId($id)
            ]
        );
    }

    public function update(): void
    {
        $this->protect();

        $id = (int) $this->request->input(
            'id',
            0
        );

        try {

            $this->userService->update(
                $id,
                $this->request->all()
            );

            header(
                'Location: /public/users?updated=1'
            );

            exit;

        } catch (\Throwable $exception) {

            $user = $this->userService->find($id);

            $this->render(
                'users/edit',
                [
                    'title' => 'Edit User',
                    'user' => $user,
                    'roles' => $this->userService->roles(),
                    'userRoleId' => (int) $this->request->input(
                        'role_id',
                        0
                    ),
                    'error' => $exception->getMessage()
                ]
            );
        }
    }

    public function toggleStatus(): void
    {
        $this->protect();

        $id = (int) $this->request->input(
            'id',
            0
        );

        try {

            $this->userService->toggleStatus(
                $id,
                (int) ($_SESSION['user_id'] ?? 0)
            );

            header(
                'Location: /public/users?status_changed=1'
            );

        } catch (\Throwable $exception) {

            header(
                'Location: /public/users?error=' .
                urlencode($exception->getMessage())
            );
        }

        exit;
    }

    public function resetPasswordForm(): void
    {
        $this->protect();

        $id = (int) $this->request->input(
            'id',
            0
        );

        $user = $this->userService->find($id);

        if ($user === null) {
            throw new RuntimeException(
                'User not found.'
            );
        }

        $this->render(
            'users/reset_password',
            [
                'title' => 'Reset Password',
                'user' => $user
            ]
        );
    }

    public function resetPassword(): void
    {
        $this->protect();

        $id = (int) $this->request->input(
            'id',
            0
        );

        try {

            $this->userService->resetPassword(
                $id,
                (string) $this->request->input(
                    'password',
                    ''
                ),
                (string) $this->request->input(
                    'password_confirmation',
                    ''
                )
            );

            header(
                'Location: /public/users?password_reset=1'
            );

            exit;

        } catch (\Throwable $exception) {

            $this->render(
                'users/reset_password',
                [
                    'title' => 'Reset Password',
                    'user' => $this->userService->find($id),
                    'error' => $exception->getMessage()
                ]
            );
        }
    }
}