"""AIS generator.

Emits NDJSON AIS records along a waypointed track. The MAC sensor CSV format
is kept verbatim by `mac_generator.py`; AIS is NDJSON only per the spec.
"""
from __future__ import annotations

import random
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import Any

from .common import iso_utc, interp_waypoints, time_range, vessel_lookup


@dataclass
class AisTrack:
    mmsi: int
    waypoints: list[tuple[datetime, float, float]]
    cadence_s: float = 10.0
    dark_windows: list[tuple[datetime, datetime]] = field(default_factory=list)
    destination: str = ""
    nav_status: int = 0  # 0 = under way using engine
    speed_jitter_kn: float = 0.4
    course_jitter_deg: float = 2.0
    spoof_position_offset: tuple[float, float] | None = None  # (lat_offset, lon_offset) applied to broadcast
    seed: int | None = None


def emit_ais(track: AisTrack) -> list[dict[str, Any]]:
    rng = random.Random(track.seed)
    vessels = vessel_lookup()
    v = vessels.get(track.mmsi, {})
    name = v.get("name", "UNKNOWN")
    ship_type = v.get("ais_type", 0)
    loa = v.get("loa_m", 0)
    beam = v.get("beam_m", 0)
    callsign = v.get("callsign", "")
    imo = v.get("imo", 0)
    out: list[dict[str, Any]] = []
    start = track.waypoints[0][0]
    end = track.waypoints[-1][0]
    for t in time_range(start, end, track.cadence_s):
        # drop messages during dark windows
        if any(a <= t < b for a, b in track.dark_windows):
            continue
        lat, lon, sog_kn, cog = interp_waypoints(track.waypoints, t)
        if track.spoof_position_offset:
            lat += track.spoof_position_offset[0]
            lon += track.spoof_position_offset[1]
        sog_kn = max(0.0, sog_kn + rng.gauss(0.0, track.speed_jitter_kn))
        cog = (cog + rng.gauss(0.0, track.course_jitter_deg)) % 360.0
        out.append({
            "timestamp": iso_utc(t),
            "ts_epoch_ms": int(t.timestamp() * 1000),
            "mmsi": track.mmsi,
            "imo": imo,
            "name": name,
            "callsign": callsign,
            "ship_type": ship_type,
            "loa_m": loa,
            "beam_m": beam,
            "lat": round(lat, 6),
            "lon": round(lon, 6),
            "sog_kn": round(sog_kn, 2),
            "cog_deg": round(cog, 1),
            "heading_deg": round(cog, 0),
            "nav_status": track.nav_status,
            "destination": track.destination,
            "msg_class": "A",
            "source_receiver": "AIS-COAST-FIN",
        })
    return out


def ais_snapshot_geojson(records: list[dict[str, Any]]) -> list[dict[str, Any]]:
    """Convert AIS records to a GeoJSON FeatureCollection (last seen per MMSI)."""
    by_mmsi: dict[int, dict[str, Any]] = {}
    for r in records:
        by_mmsi[r["mmsi"]] = r
    feats = []
    for r in by_mmsi.values():
        feats.append({
            "type": "Feature",
            "geometry": {"type": "Point", "coordinates": [r["lon"], r["lat"]]},
            "properties": {k: v for k, v in r.items() if k not in ("lat", "lon")},
        })
    return feats
