-- 004_trips_for_range_rpc.sql
-- Multi-day variant of trips_for_day. The 14-day cap is enforced here in SQL
-- so PostgREST can't be tricked into asking for an absurd range via direct RPC.

CREATE OR REPLACE FUNCTION public.trips_for_range(
  p_start         date,
  p_end           date,
  p_cost_centres  text[] DEFAULT NULL
) RETURNS TABLE (
  trip_id        bigint,
  imei           text,
  vehicle_name   text,
  vehicle_number text,
  cost_centre    text,
  start_time     timestamptz,
  end_time       timestamptz,
  distance_km    numeric,
  path_geojson   json,
  timestamps_rel int[]
)
LANGUAGE plpgsql STABLE
SECURITY DEFINER
SET search_path = public, tracksolid
AS $$
BEGIN
  IF p_start IS NULL OR p_end IS NULL OR p_end < p_start THEN
    RAISE EXCEPTION 'Invalid date range: p_start=%, p_end=%', p_start, p_end;
  END IF;
  IF (p_end - p_start) > 13 THEN
    RAISE EXCEPTION 'Range too large: max 14 days, got %', (p_end - p_start + 1);
  END IF;

  RETURN QUERY
  WITH range_trips AS (
    SELECT v.*
    FROM public.trips_viz_v1 v
    WHERE v.start_time::date BETWEEN p_start AND p_end
      AND (p_cost_centres IS NULL OR v.cost_centre = ANY(p_cost_centres))
  )
  SELECT
    rt.trip_id,
    rt.imei,
    rt.vehicle_name,
    rt.vehicle_number,
    rt.cost_centre,
    rt.start_time,
    rt.end_time,
    rt.distance_km,
    ST_AsGeoJSON(ST_MakeLine(ph.geom ORDER BY ph.gps_time))::json    AS path_geojson,
    array_agg(
      EXTRACT(EPOCH FROM ph.gps_time - rt.start_time)::int
      ORDER BY ph.gps_time
    )                                                                AS timestamps_rel
  FROM range_trips rt
  JOIN tracksolid.position_history ph
    ON ph.imei     = rt.imei
   AND ph.gps_time BETWEEN rt.start_time AND rt.end_time
   AND ph.geom IS NOT NULL
  GROUP BY rt.trip_id, rt.imei, rt.vehicle_name, rt.vehicle_number,
           rt.cost_centre, rt.start_time, rt.end_time, rt.distance_km
  HAVING count(ph.geom) >= 2;
END;
$$;

GRANT EXECUTE ON FUNCTION public.trips_for_range(date, date, text[]) TO viz_anon;
