<?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\AuthorizationService;
use App\Modules\Administration\Services\EmployeeDocumentService;
use App\Modules\Administration\Services\EmployeeFamilyService;
use App\Modules\Administration\Services\EmployeeService;
use RuntimeException;
use System\Http\Request;
use System\View\View;
use App\Modules\Administration\Services\EmployeeTrainingService;
use App\Modules\Administration\Services\EmployeeTransferService;
use App\Modules\Administration\Services\EmployeeRankPromotionService;

final class EmployeeController extends Controller
{
public function __construct(
    private AuthenticationService $authentication,
    private AuthorizationService $authorization,
    private EmployeeService $employeeService,
    private EmployeeFamilyService $familyService,
    private EmployeeDocumentService $documentService,
    private EmployeeTrainingService $trainingService,
    private EmployeeTransferService $transferService,
    private EmployeeRankPromotionService $promotionService,
    private Request $request,
    View $view
) {
    parent::__construct($view);
}

    private function protect(): void
    {
        if (!$this->authentication->check()) {
            header('Location: /public/login');
            exit;
        }
    }

    private function requireAdministrator(): void
    {
        if (!$this->authorization->isAdministrator()) {
            header('Location: /public/403');
            exit;
        }
    }

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

        $this->render(
            'employees/index',
            [
                'title' =>
                    'Employee Management',

                'employees' =>
                    $this->employeeService->all(),

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

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

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

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

        $formData =
            $this->employeeService->formData();

        $this->render(
            'employees/create',
            array_merge(
                [
                    'title' =>
                        'Create Employee'
                ],
                $formData
            )
        );
    }

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

        try {
            $photo =
                $_FILES['photo']
                ?? null;

            $this->employeeService->create(
                $this->request->all(),
                $photo
            );

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

            exit;

        } catch (\Throwable $exception) {

            $formData =
                $this->employeeService->formData();

            $this->render(
                'employees/create',
                array_merge(
                    [
                        'title' =>
                            'Create Employee',

                        'error' =>
                            $exception->getMessage(),

                        'old' =>
                            $this->request->all()
                    ],
                    $formData
                )
            );
        }
    }

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

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

        $employee =
            $this->employeeService->find(
                $id
            );

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

        $formData =
            $this->employeeService->formData();

        $this->render(
            'employees/edit',
            array_merge(
                [
                    'title' =>
                        'Edit Employee',

                    'employee' =>
                        $employee
                ],
                $formData
            )
        );
    }

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

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

        try {
            $photo =
                $_FILES['photo']
                ?? null;

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

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

            exit;

        } catch (\Throwable $exception) {

            $formData =
                $this->employeeService->formData();

            $this->render(
                'employees/edit',
                array_merge(
                    [
                        'title' =>
                            'Edit Employee',

                        'employee' =>
                            $this->employeeService
                                ->find($id),

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

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

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

        $employee =
            $this->employeeService->profile(
                $id
            );

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

        $this->render(
            'employees/show',
            [
                'title' =>
                    'Employee Profile',

                'employee' =>
                    $employee,

                'familyMembers' =>
                    $this->familyService
                        ->byEmployee($id),

                'familyCreated' =>
                    $this->request->input(
                        'family_created'
                    ),

                'familyUpdated' =>
                    $this->request->input(
                        'family_updated'
                    ),

                'familyDeactivated' =>
                    $this->request->input(
                        'family_deactivated'
                    ),

                'familyError' =>
                    $this->request->input(
                        'family_error'
                    ),

                'documents' =>
                    $this->documentService
                        ->byEmployee($id),

                'documentCreated' =>
                    $this->request->input(
                        'document_created'
                    ),

                'documentDeactivated' =>
                    $this->request->input(
                        'document_deactivated'
                    ),
                    'transferHistory' =>
    $this->transferService
        ->byEmployee($id),

'transferCreated' =>
    $this->request->input(
        'transfer_created'
    ),
'transferUpdated' =>
    $this->request->input(
        'transfer_updated'
    ),
'transferStatusUpdated' =>
    $this->request->input(
        'transfer_status_updated'
    ),

'transferError' =>
    $this->request->input(
        'transfer_error'
    ),

'documentError' =>
    $this->request->input(
        'document_error'
    ),

'trainingHistory' =>
    $this->trainingService
        ->byEmployee($id),

'trainingCreated' =>
    $this->request->input(
        'training_created'
    ),

'trainingStatusUpdated' =>
    $this->request->input(
        'training_status_updated'
    ),

'trainingError' =>
    $this->request->input(
        'training_error'
    ),
    'promotionHistory' =>
    $this->promotionService
        ->byEmployee($id),

'promotionRanks' =>
    $this->promotionService
        ->ranks(),

'promotionCreated' =>
    $this->request->input(
        'promotion_created'
    ),
'promotionUpdated' =>
    $this->request->input(
        'promotion_updated'
    ),
'promotionStatusUpdated' =>
    $this->request->input(
        'promotion_status_updated'
    ),

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