<?php

namespace App\MessageHandler;

use App\Entity\SargassumObservation;
use App\Message\IngestionScheduleMessage;
use App\Service\Forecast\DriftSimulationService;
use App\Service\Forecast\ImpactScoreService;
use App\Service\Ingestion\IngestionService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

/**
 * Exécute le pipeline complet à chaque tick du scheduler :
 *   1. Ingestion Sentinel-2/3 pour chaque zone Antilles
 *   2. Calcul des forecasts de dérive pour les nouvelles observations
 *   3. Calcul des ImpactScores pour tous les spots côtiers
 */
#[AsMessageHandler]
final class IngestionScheduleHandler
{
    // Zones d'intérêt — même liste que IngestSentinelCommand
    private const ZONES = [
        'martinique'   => [-61.30, 14.30, -60.70, 14.90],
        'guadeloupe'   => [-61.90, 15.80, -61.00, 16.60],
        'sainte-lucie' => [-61.10, 13.70, -60.80, 14.20],
        'barbade'      => [-59.80, 13.00, -59.30, 13.40],
        'saint-martin' => [-63.20, 17.80, -62.90, 18.20],
    ];

    public function __construct(
        private IngestionService       $ingestion,
        private DriftSimulationService $drift,
        private ImpactScoreService     $scores,
        private EntityManagerInterface $em,
        private LoggerInterface        $logger,
    ) {}

    public function __invoke(IngestionScheduleMessage $message): void
    {
        $date = new \DateTimeImmutable('yesterday');
        $this->logger->info('Scheduled ingestion started', ['date' => $date->format('Y-m-d')]);

        // Étape 1 : ingestion de toutes les zones
        foreach (self::ZONES as $name => $bbox) {
            try {
                $this->ingestion->ingestWithFallback($bbox, $date);
                $this->logger->info('Zone ingested', ['zone' => $name]);
            } catch (\Throwable $e) {
                $this->logger->error('Ingestion failed', ['zone' => $name, 'error' => $e->getMessage()]);
            }
        }

        // Étape 2 : forecasts pour les observations sans prévision
        $observations = $this->em->getRepository(SargassumObservation::class)
            ->createQueryBuilder('o')
            ->leftJoin('o.forecasts', 'f')
            ->where('f.id IS NULL')
            ->orderBy('o.detectedAt', 'DESC')
            ->setMaxResults(10)
            ->getQuery()
            ->getResult();

        foreach ($observations as $observation) {
            try {
                $forecasts = $this->drift->computeForecasts($observation);
                $this->scores->computeForObservation($observation, $forecasts);
                $this->logger->info('Forecasts computed', ['observation' => (string) $observation->getId()]);
            } catch (\Throwable $e) {
                $this->logger->error('Forecast failed', [
                    'observation' => (string) $observation->getId(),
                    'error'       => $e->getMessage(),
                ]);
            }
        }

        $this->logger->info('Scheduled ingestion completed');
    }
}
