<?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\RoleService;
use RuntimeException;
use System\Http\Request;
use System\View\View;

final class RoleController extends Controller
{
    public function __construct(
        private AuthenticationService $authentication,
        private RoleService $roleService,
        private Request $request,
        View $view
    ) {
        parent::__construct($view);
    }

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

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

            exit;
        }
    }

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

$this->render(
    'roles/index',
    [
        'title' => 'Role Management',

        'roles' => $this->roleService->all(),

        'created' => $this->request->input(
            'created'
        ),

        'updated' => $this->request->input(
            'updated'
        ),

        'statusChanged' => $this->request->input(
            'status_changed'
        ),

        'permissionsUpdated' => $this->request->input(
            'permissions_updated'
        ),

        'error' => $this->request->input(
            'error'
        )
    ]
);
    }

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

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

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

        try {

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

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

            exit;

        } catch (\Throwable $exception) {

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

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

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

        $role = $this->roleService->find($id);

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

        $this->render(
            'roles/edit',
            [
                'title' => 'Edit Role',
                'role' => $role
            ]
        );
    }

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

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

        try {

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

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

            exit;

        } catch (\Throwable $exception) {

            $this->render(
                'roles/edit',
                [
                    'title' => 'Edit Role',
                    'role' =>
                        $this->roleService->find($id),
                    'error' =>
                        $exception->getMessage()
                ]
            );
        }
    }

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

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

        try {

            $this->roleService->toggleStatus(
                $id
            );

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

        } catch (\Throwable $exception) {

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

        exit;
    }
    public function permissions(): void
{
    $this->protect();

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

    $role = $this->roleService->find(
        $id
    );

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

    $this->render(
        'roles/permissions',
        [
            'title' =>
                'Role Permissions',

            'role' =>
                $role,

            'permissions' =>
                $this->roleService
                    ->permissions(),

            'assignedPermissionIds' =>
                $this->roleService
                    ->rolePermissionIds($id)
        ]
    );
}

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

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

    $permissionIds =
        $_POST['permissions'] ?? [];

    if (!is_array($permissionIds)) {
        $permissionIds = [];
    }

    try {

        $this->roleService
            ->savePermissions(
                $id,
                $permissionIds
            );

        header(
            'Location: /public/roles?permissions_updated=1'
        );

        exit;

    } catch (\Throwable $exception) {

        $role =
            $this->roleService->find($id);

        $this->render(
            'roles/permissions',
            [
                'title' =>
                    'Role Permissions',

                'role' =>
                    $role,

                'permissions' =>
                    $this->roleService
                        ->permissions(),

                'assignedPermissionIds' =>
                    array_map(
                        'intval',
                        $permissionIds
                    ),

                'error' =>
                    $exception->getMessage()
            ]
        );
    }
}
}