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

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

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

        try {
            $document =
                $_FILES['document_file']
                ?? null;

            $this->promotionService->create(
                $employeeId,
                $this->request->all(),
                $document
            );

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

            exit;
        } catch (\Throwable $exception) {
            header(
                'Location: /public/employees/show?id='
                . $employeeId
                . '&promotion_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 {
        $document =
            $_FILES['document_file']
            ?? null;

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

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

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

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

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

            exit;
        }
    }

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

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

        $promotion =
            $this->promotionService->find($id);

        if ($promotion === null) {
            http_response_code(404);
            exit('Promotion record not found.');
        }

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

        $relativePath = (string) (
            $promotion['document_file_path']
            ?? ''
        );

        if ($relativePath === '') {
            http_response_code(404);
            exit(
                'Promotion document is not available.'
            );
        }

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

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

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

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