<?php

declare(strict_types=1);

namespace App\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Entity\Employee;
use App\Repository\EmployeeRepository;
use App\Service\WorkHours\YearlyHoursExportBuilder;
use DateTimeImmutable;
use Dompdf\Dompdf;
use Dompdf\Options;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
use Twig\Environment;

class EmployeeYearlyHoursPrintProvider implements ProviderInterface
{
    public function __construct(
        private Environment $twig,
        private readonly RequestStack $requestStack,
        private EmployeeRepository $employeeRepository,
        private YearlyHoursExportBuilder $exportBuilder,
    ) {}

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): Response
    {
        $request = $this->requestStack->getCurrentRequest();
        if (!$request) {
            return new Response('Missing request.', Response::HTTP_BAD_REQUEST);
        }

        $employeeId = (int) $request->query->get('employeeId', '0');
        if ($employeeId <= 0) {
            throw new UnprocessableEntityHttpException('employeeId must be a positive integer.');
        }

        $employee = $this->employeeRepository->find($employeeId);
        if (!$employee instanceof Employee) {
            throw new NotFoundHttpException('Employee not found.');
        }

        $yearRaw = (string) $request->query->get('year');
        if (!preg_match('/^\d{4}$/', $yearRaw)) {
            throw new UnprocessableEntityHttpException('year must use YYYY format.');
        }
        $year = (int) $yearRaw;

        $monthRaw = (string) $request->query->get('month', '');
        $month    = null;
        if ('' !== $monthRaw) {
            if (!preg_match('/^(?:0?[1-9]|1[0-2])$/', $monthRaw)) {
                throw new UnprocessableEntityHttpException('month must be between 1 and 12.');
            }
            $month = (int) $monthRaw;
        }

        if (null !== $month) {
            $from = new DateTimeImmutable(sprintf('%d-%02d-01', $year, $month));
            $to   = $from->modify('last day of this month');
        } else {
            $from = new DateTimeImmutable("{$year}-01-01");
            $to   = new DateTimeImmutable("{$year}-12-31");
        }

        $entries = $this->exportBuilder->buildForEmployee($employee, $from, $to);

        $employeeName  = trim(($employee->getLastName() ?? '').' '.($employee->getFirstName() ?? ''));
        $contractLabel = $this->exportBuilder->buildContractLabel($employee);

        $options = new Options();
        $options->set('isRemoteEnabled', true);

        $dompdf = new Dompdf($options);
        $html   = $this->twig->render('employee-yearly-hours/print.html.twig', [
            'employeeName'  => $employeeName,
            'contractLabel' => $contractLabel,
            'year'          => $year,
            'month'         => $month,
            'segments'      => $entries[0]['segments'] ?? [],
        ]);

        $dompdf->loadHtml($html);
        $dompdf->setPaper('A4', 'portrait');
        $dompdf->render();

        $filename = null !== $month
            ? sprintf(
                '%s_%s_%d-%02d.pdf',
                $this->sanitizeFilename($employee->getLastName() ?? ''),
                $this->sanitizeFilename($employee->getFirstName() ?? ''),
                $year,
                $month,
            )
            : sprintf(
                '%s_%s_%d.pdf',
                $this->sanitizeFilename($employee->getLastName() ?? ''),
                $this->sanitizeFilename($employee->getFirstName() ?? ''),
                $year,
            );

        return new Response($dompdf->output(), Response::HTTP_OK, [
            'Content-Type'        => 'application/pdf',
            'Content-Disposition' => 'inline; filename="'.$filename.'"',
        ]);
    }

    private function sanitizeFilename(string $name): string
    {
        $name = str_replace(' ', '_', $name);

        return preg_replace('/[^a-zA-Z0-9_\-]/', '', $name) ?? $name;
    }
}
