<?php

declare(strict_types=1);

namespace App\Module\Absence\Infrastructure\Controller;

use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

/**
 * Streams the justification file of an absence request. Owner or admin only.
 */
class AbsenceJustificationDownloadController extends AbstractController
{
    public function __construct(
        private readonly AbsenceRequestRepositoryInterface $requestRepository,
        private readonly Security $security,
        private readonly string $uploadDir,
    ) {}

    #[Route('/api/absence_requests/{id}/justificatif', name: 'absence_justification_download', methods: ['GET'], priority: 1)]
    #[IsGranted('ROLE_USER')]
    public function __invoke(int $id): BinaryFileResponse
    {
        $absence = $this->requestRepository->findById($id);
        if (null === $absence) {
            throw new NotFoundHttpException('Absence request not found.');
        }

        if (!$this->security->isGranted('ROLE_ADMIN') && $absence->getUser() !== $this->security->getUser()) {
            throw new AccessDeniedHttpException('You do not have access to this file.');
        }

        $fileName = $absence->getJustificationFileName();
        if (null === $fileName) {
            throw new NotFoundHttpException('No justification file for this request.');
        }

        $filePath = $this->uploadDir.'/'.$fileName;
        if (!file_exists($filePath)) {
            throw new NotFoundHttpException('File not found on disk.');
        }

        $response = new BinaryFileResponse($filePath);
        $mimeType = mime_content_type($filePath) ?: 'application/octet-stream';

        $disposition = (str_starts_with($mimeType, 'image/') || 'application/pdf' === $mimeType)
            ? ResponseHeaderBag::DISPOSITION_INLINE
            : ResponseHeaderBag::DISPOSITION_ATTACHMENT;

        $response->setContentDisposition($disposition, $fileName);
        $response->headers->set('Content-Type', $mimeType);

        return $response;
    }
}
