<?php

namespace App\Controller;

use App\Ocr\GeminiOcrClient;
use App\Ocr\OcrParser;
use App\Service\ImageStorage;
use App\Service\ImageValidator;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

/**
 * OCR d'une image (plaque ou VIN) via Gemini. Port de app/api/ocr/route.ts.
 */
// L'OCR ne sert qu'au scan : réservé aux groupes qui peuvent créer (LECTEUR exclu).
#[IsGranted('SCAN_CREATE')]
final class OcrController extends AbstractController
{
    private const ALLOWED_TYPES = ['plate', 'vin', 'auto'];

    #[Route('/api/ocr', name: 'app_ocr', methods: ['POST'])]
    public function ocr(
        Request $request,
        ImageValidator $validator,
        GeminiOcrClient $gemini,
        OcrParser $parser,
        ImageStorage $imageStorage,
        \App\Service\S3Settings $s3,
        LoggerInterface $logger,
    ): JsonResponse {
        if (!str_contains((string) $request->headers->get('Content-Type'), 'application/json')) {
            return $this->json(['error' => 'Content-Type must be application/json'], Response::HTTP_BAD_REQUEST);
        }

        $body = json_decode($request->getContent(), true);
        if (!\is_array($body)) {
            return $this->json(['error' => 'Invalid JSON body'], Response::HTTP_BAD_REQUEST);
        }

        $image = $body['image'] ?? null;
        $type = $body['type'] ?? null;
        $filename = $body['filename'] ?? null;

        if (!\is_string($image) || '' === $image) {
            return $this->json(['error' => "Missing or invalid 'image' field"], Response::HTTP_BAD_REQUEST);
        }
        if (!$validator->isValidBase64($image)) {
            return $this->json(['error' => 'Invalid base64 image data'], Response::HTTP_BAD_REQUEST);
        }
        if (!\is_string($type) || !\in_array($type, self::ALLOWED_TYPES, true)) {
            return $this->json(['error' => "Invalid 'type' field. Must be plate, vin, or auto"], Response::HTTP_BAD_REQUEST);
        }

        $safeFilename = \is_string($filename) ? $validator->sanitizeFilename($filename) : 'unknown';
        $sessionId = $body['sessionId'] ?? null;
        $imageId = $body['imageId'] ?? null;

        try {
            // Stockage local de l'image AVANT l'OCR (récupérable même si l'OCR échoue).
            // En mode S3, on NE stocke PAS en local : le navigateur téléverse la photo
            // directement sur S3 (le serveur OVH ne pouvant pas joindre S3).
            if (!$s3->isStorageEnabled()
                && \is_string($sessionId) && \is_string($imageId)
                && ImageStorage::isValidId($sessionId) && ImageStorage::isValidId($imageId)
            ) {
                try {
                    $imageStorage->store($this->getUser()->getUserIdentifier(), $sessionId, $imageId, $image);
                } catch (\Throwable $e) {
                    // Stockage non bloquant : on log et on continue l'OCR.
                    $logger->warning('Échec stockage image', ['exception' => $e]);
                }
            }

            ['raw' => $raw, 'type' => $detectedType] = $gemini->recognize($image, $type);

            $parseResult = 'plate' === $detectedType ? $parser->parsePlate($raw) : $parser->parseVin($raw);

            return $this->json([
                'raw' => $raw,
                'corrected' => $parseResult->corrected ?? '',
                'type' => $detectedType,
                'confidence' => $parseResult->confidence,
                'filename' => $safeFilename,
            ], Response::HTTP_OK, [
                'Cache-Control' => 'no-store',
                'X-Content-Type-Options' => 'nosniff',
            ]);
        } catch (\Throwable $e) {
            $logger->error('Erreur OCR', ['exception' => $e]);

            return $this->json(['error' => 'Le traitement OCR a échoué.'], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
}
