<?php

namespace App\Service\Ocean;

use Psr\Log\LoggerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * Récupère les courants de surface océaniques via OSCAR (NOAA/ERDDAP).
 *
 * Source : Ocean Surface Current Analyses Real-time (OSCAR)
 * Résolution : 1/3° (~37km), latence ~5 jours (données les plus récentes)
 * Accès : gratuit, sans clé API, JSON direct via ERDDAP
 *
 * Physique :
 *   La dérive des sargasses = vent Stokes (3% vent) + courant de surface (100%).
 *   Pour les prévisions 6–48h, les courants Caraïbes évoluent sur des échelles de
 *   1–2 semaines → utiliser le courant le plus récent comme constante est justifié.
 *
 * Extension vers CMEMS (meilleure qualité) :
 *   Remplacer l'URL ERDDAP par le endpoint CMEMS avec CMEMS_API_KEY en env.
 */
class OceanCurrentClient
{
    private const ERDDAP_URL = 'https://coastwatch.pfeg.noaa.gov/erddap/griddap/jplOscar.json';

    public function __construct(
        private HttpClientInterface $httpClient,
        private LoggerInterface     $logger,
    ) {}

    /**
     * Retourne le vecteur courant de surface (u, v) en m/s au point donné.
     * u = composante Est-Ouest (positif → vers l'Est)
     * v = composante Nord-Sud (positif → vers le Nord)
     *
     * Retourne null si OSCAR est indisponible (drift wind-only en fallback).
     *
     * @return array{u: float, v: float}|null
     */
    public function getSurfaceCurrent(float $lat, float $lng): ?array
    {
        // OSCAR résolution 1/3° : arrondir au point de grille le plus proche
        $latGrid = round($lat * 3) / 3;
        $lngGrid = round($lng * 3) / 3;

        // ERDDAP constraint syntax : [(last)][(lat)][(lng)]
        // (last) = timestamp le plus récent disponible
        $query = sprintf(
            '?u%%5B(last)%%5D%%5B(%.4f)%%5D%%5B(%.4f)%%5D,v%%5B(last)%%5D%%5B(%.4f)%%5D%%5B(%.4f)%%5D',
            $latGrid, $lngGrid, $latGrid, $lngGrid
        );

        try {
            $response = $this->httpClient->request('GET', self::ERDDAP_URL . $query, [
                'timeout' => 8,
            ]);

            $data = $response->toArray();
            $rows = $data['table']['rows'] ?? [];

            if (empty($rows)) {
                $this->logger->warning('OSCAR: no data returned', ['lat' => $lat, 'lng' => $lng]);
                return null;
            }

            // Colonnes ERDDAP : [time, latitude, longitude, u, v] (ordre peut varier)
            $cols = array_flip($data['table']['columnNames'] ?? []);
            $row  = $rows[0];

            $u = isset($cols['u']) && $row[$cols['u']] !== null ? (float) $row[$cols['u']] : null;
            $v = isset($cols['v']) && $row[$cols['v']] !== null ? (float) $row[$cols['v']] : null;

            if ($u === null || $v === null) {
                $this->logger->info('OSCAR: NaN at point, likely land mask', ['lat' => $lat, 'lng' => $lng]);
                return null;
            }

            $this->logger->debug('OSCAR current', ['lat' => $lat, 'lng' => $lng, 'u' => $u, 'v' => $v]);

            return ['u' => $u, 'v' => $v];

        } catch (\Throwable $e) {
            $this->logger->warning('OSCAR unavailable, using wind-only drift', ['error' => $e->getMessage()]);
            return null;
        }
    }
}
