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

final class EmployeeTrainingController extends Controller
{
    public function __construct(
        private AuthenticationService $authentication,
        private AuthorizationService $authorization,
        private EmployeeTrainingService $trainingService,
        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 store(): void
    {
        $this->protect();
        $this->requireAdministrator();

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

        try {
            $certificate =
                $_FILES['certificate_file']
                ?? null;

            $this->trainingService->create(
                $employeeId,
                $this->request->all(),
                $certificate
            );

            header(
                'Location: /public/employees/show?id='
                . $employeeId
                . '&training_created=1'
            );

            exit;

        } catch (\Throwable $exception) {
            header(
                'Location: /public/employees/show?id='
                . $employeeId
                . '&training_error='
                . urlencode(
                    $exception->getMessage()
                )
            );

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

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

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

    try {

        $certificate =
            $_FILES['certificate_file']
            ?? null;

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

        header(
            'Location: /public/employees/show?id='
            . $employeeId
            . '&training_updated=1'
        );

        exit;

    } catch (\Throwable $exception) {

        header(
            'Location: /public/employees/show?id='
            . $employeeId
            . '&training_error='
            . urlencode(
                $exception->getMessage()
            )
        );

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

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

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

        try {
            $this->trainingService
                ->toggleStatus($id);

            header(
                'Location: /public/employees/show?id='
                . $employeeId
                . '&training_status_updated=1'
            );

            exit;

        } catch (\Throwable $exception) {
            header(
                'Location: /public/employees/show?id='
                . $employeeId
                . '&training_error='
                . urlencode(
                    $exception->getMessage()
                )
            );

            exit;
        }
    }

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

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

        $training =
            $this->trainingService->find($id);

        if ($training === null) {
            http_response_code(404);

            exit(
                'Training record not found.'
            );
        }

        if (
            (int) (
                $training['status']
                ?? 0
            ) !== 1
        ) {
            http_response_code(403);

            exit(
                'Training record is inactive.'
            );
        }

        $relativePath = (string) (
            $training[
                'certificate_file_path'
            ]
            ?? ''
        );

        if ($relativePath === '') {
            http_response_code(404);

            exit(
                'Certificate file is not available.'
            );
        }

        $filePath =
            PUBLIC_PATH
            . '/'
            . ltrim(
                $relativePath,
                '/'
            );

        if (
            !is_file($filePath)
            || !is_readable($filePath)
        ) {
            http_response_code(404);

            exit(
                'Certificate file not found.'
            );
        }

        $mimeType = (string) (
            $training[
                'certificate_mime_type'
            ]
            ?? 'application/octet-stream'
        );

        $originalName = (string) (
            $training[
                'certificate_original_name'
            ]
            ?? basename($filePath)
        );

        $safeName = str_replace(
            [
                '"',
                "\r",
                "\n"
            ],
            '',
            $originalName
        );

        header(
            'Content-Type: '
            . $mimeType
        );

        header(
            'Content-Length: '
            . filesize($filePath)
        );

        header(
            'Content-Disposition: inline; filename="'
            . $safeName
            . '"'
        );

        header(
            'X-Content-Type-Options: nosniff'
        );

        readfile($filePath);

        exit;
    }
}