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

final class EmployeeDocumentController extends Controller
{
    public function __construct(
        private AuthenticationService $authentication,
        private AuthorizationService $authorization,
        private EmployeeDocumentService $documentService,
        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 {
            $file =
                $_FILES['document_file']
                ?? [];

            $this->documentService->create(
                $employeeId,
                $this->request->all(),
                $file
            );

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

            exit;

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

            exit;
        }
    }

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

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

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

        try {
            $this->documentService
                ->deactivate($id);

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

            exit;

        } catch (\Throwable $exception) {
            header(
                'Location: /public/employees/show?id='
                . $employeeId
                . '&document_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->documentService
                ->toggleStatus($id);

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

            exit;

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

            exit;
        }
    }

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

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

        $document =
            $this->documentService->find($id);

        if ($document === null) {
            http_response_code(404);
            exit('Document not found.');
        }

        if (
            (int) (
                $document['status']
                ?? 0
            ) !== 1
        ) {
            http_response_code(403);
            exit('Document is inactive.');
        }

        $relativePath = (string) (
            $document['file_path']
            ?? ''
        );

        if ($relativePath === '') {
            http_response_code(404);
            exit(
                'Document file path is missing.'
            );
        }

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

        if (
            !is_file($filePath)
            || !is_readable($filePath)
        ) {
            http_response_code(404);
            exit(
                'Document file not found.'
            );
        }

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

        $originalName = (string) (
            $document['original_file_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;
    }
}