<?php

namespace App\Twig;

use App\Entity\ScanSession;
use App\Repository\UserRepository;
use App\Security\Voter\UserManagementVoter;
use App\Service\ConcessionsProvider;
use App\Service\S3Presigner;
use App\Service\S3Settings;
use App\Service\VehicleErrorChecker;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;

/**
 * Fonctions Twig de l'app. `pending_users_count()` alimente le badge « demandes en attente »
 * de la navbar (ne compte que si l'utilisateur courant peut valider les demandes).
 * Les filtres `concession_name`/`concession_names` résolvent les IDs de concession
 * stockés en base vers leur nom affichable.
 */
final class AppExtension extends AbstractExtension
{
    public function __construct(
        private readonly UserRepository $users,
        private readonly Security $security,
        private readonly ConcessionsProvider $concessions,
        private readonly VehicleErrorChecker $errors,
        private readonly S3Settings $s3,
        private readonly S3Presigner $presigner,
        private readonly UrlGeneratorInterface $urls,
    ) {
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('pending_users_count', $this->pendingUsersCount(...)),
            new TwigFunction('plate_in_error', $this->errors->plateInError(...)),
            new TwigFunction('vin_in_error', $this->errors->vinInError(...)),
            new TwigFunction('image_url', $this->imageUrl(...)),
        ];
    }

    /**
     * URL d'affichage d'une photo. Si la session est sur S3 → URL pré-signée S3
     * (chargée directement par le navigateur, sans passer par le serveur OVH) ;
     * sinon → route locale `app_image` (BinaryFileResponse depuis var/uploads).
     *
     * @param string|null $s3Key clé S3 explicite (photo héritée d'une fusion d'une autre session)
     */
    public function imageUrl(ScanSession $session, ?string $imageId, ?string $s3Key = null): string
    {
        if (null === $imageId || '' === $imageId) {
            return '';
        }

        if (null !== $s3Key && '' !== $s3Key && $this->s3->isConfigured()) {
            return $this->presigner->presignGet($s3Key);
        }

        $prefix = $session->getS3Prefix();
        if (null !== $prefix && '' !== $prefix && $this->s3->isConfigured()) {
            return $this->presigner->presignGet($this->s3->objectKey($prefix, $imageId));
        }

        return $this->urls->generate('app_image', [
            'sessionId' => $session->getId(),
            'imageId' => $imageId,
        ]);
    }

    public function getFilters(): array
    {
        return [
            new TwigFilter('concession_name', $this->concessionName(...)),
            new TwigFilter('concession_names', $this->concessionNames(...)),
            new TwigFilter('scan_type_label', ScanSession::scanTypeLabel(...)),
        ];
    }

    public function pendingUsersCount(): int
    {
        if (!$this->security->isGranted(UserManagementVoter::VALIDATE)) {
            return 0;
        }

        return $this->users->countPending();
    }

    public function concessionName(?string $id): string
    {
        return null === $id ? '' : $this->concessions->label($id);
    }

    /**
     * @param array<int, string>|null $ids
     *
     * @return list<string>
     */
    public function concessionNames(?array $ids): array
    {
        return null === $ids ? [] : $this->concessions->names($ids);
    }
}
