<?php

namespace App\Controller;

use Doctrine\DBAL\Connection;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/api/observations', name: 'api_observations_')]
class ObservationController extends AbstractController
{
    public function __construct(private Connection $connection) {}

    /**
     * GET /api/observations
     *
     * Paramètres optionnels :
     *   ?bbox=minLon,minLat,maxLon,maxLat   filtre spatial PostGIS
     *   ?date=YYYY-MM-DD                    filtre sur detected_at
     *   ?source=Sentinel-2                  filtre sur source
     */
    #[Route('', name: 'collection', methods: ['GET'])]
    public function collection(Request $request): JsonResponse
    {
        $sql = <<<SQL
            SELECT
                id,
                detected_at       AS "detectedAt",
                source,
                tile_id           AS "tileId",
                cloud_coverage    AS "cloudCoverage",
                confidence,
                afai_mean         AS "afaiMean",
                afai_std          AS "afaiStd",
                coverage_area     AS "coverageArea",
                processing_version AS "processingVersion",
                created_at        AS "createdAt",
                ST_AsGeoJSON(geometry)::json AS geometry,
                ST_AsGeoJSON(bbox)::json     AS bbox
            FROM sargassum_observation
            WHERE 1=1
        SQL;

        $params = [];
        $types  = [];

        // Filtre bbox
        $bboxParam = $request->query->get('bbox');
        if ($bboxParam !== null) {
            $parts = array_map('floatval', explode(',', $bboxParam));
            if (count($parts) === 4) {
                [$minLon, $minLat, $maxLon, $maxLat] = $parts;
                $sql .= ' AND ST_Intersects(geometry, ST_MakeEnvelope(:minLon, :minLat, :maxLon, :maxLat, 4326))';
                $params['minLon'] = $minLon;
                $params['minLat'] = $minLat;
                $params['maxLon'] = $maxLon;
                $params['maxLat'] = $maxLat;
            }
        }

        // Filtre date
        $dateParam = $request->query->get('date');
        if ($dateParam !== null) {
            $sql .= ' AND detected_at::date = :date::date';
            $params['date'] = $dateParam;
        }

        // Filtre source
        $sourceParam = $request->query->get('source');
        if ($sourceParam !== null) {
            $sql .= ' AND source = :source';
            $params['source'] = $sourceParam;
        }

        $sql .= ' ORDER BY detected_at DESC LIMIT 100';

        $rows = $this->connection->fetchAllAssociative($sql, $params, $types);

        // Décoder les champs JSON imbriqués
        foreach ($rows as &$row) {
            $row['geometry'] = $row['geometry'] ? json_decode($row['geometry'], true) : null;
            $row['bbox']     = $row['bbox']     ? json_decode($row['bbox'], true)     : null;
        }

        return $this->json(['items' => $rows, 'total' => count($rows)]);
    }

    /**
     * GET /api/observations/{id}
     */
    #[Route('/{id}', name: 'item', methods: ['GET'])]
    public function item(string $id): JsonResponse
    {
        $sql = <<<SQL
            SELECT
                id,
                detected_at       AS "detectedAt",
                source,
                tile_id           AS "tileId",
                cloud_coverage    AS "cloudCoverage",
                confidence,
                afai_mean         AS "afaiMean",
                afai_std          AS "afaiStd",
                coverage_area     AS "coverageArea",
                processing_version AS "processingVersion",
                created_at        AS "createdAt",
                ST_AsGeoJSON(geometry)::json AS geometry,
                ST_AsGeoJSON(bbox)::json     AS bbox
            FROM sargassum_observation
            WHERE id = :id
        SQL;

        $row = $this->connection->fetchAssociative($sql, ['id' => $id]);

        if ($row === false) {
            return $this->json(['error' => 'Observation not found'], 404);
        }

        $row['geometry'] = $row['geometry'] ? json_decode($row['geometry'], true) : null;
        $row['bbox']     = $row['bbox']     ? json_decode($row['bbox'], true)     : null;

        return $this->json($row);
    }
}
