"""Timestamp audit for IMU and LiDAR streams."""

from __future__ import annotations

from dataclasses import dataclass

import numpy as np

from .contracts import ImuSeries, LidarFrame


@dataclass(frozen=True)
class TimestampAuditReport:
    monotonic: bool
    epoch_count: int
    imu_rate_hz: float
    lidar_rate_hz: float
    imu_duration_s: float
    lidar_duration_s: float
    max_imu_gap_s: float
    max_lidar_gap_s: float
    notes: tuple[str, ...] = ()
    ok: bool = True


def _rate_and_gaps(times: np.ndarray) -> tuple[float, float]:
    if times.size < 2:
        return 0.0, 0.0
    dt = np.diff(times)
    positive = dt[dt > 0]
    if positive.size == 0:
        return 0.0, float("inf")
    rate = float(1.0 / np.median(positive))
    return rate, float(np.max(dt))


def audit_timestamps(imu: ImuSeries, frames: list[LidarFrame]) -> TimestampAuditReport:
    """Audit native timestamps without assuming the two clocks share an epoch."""

    notes: list[str] = []
    imu_t = imu.t_s
    lidar_t = np.asarray([frame.t_mid_s for frame in frames], dtype=float)

    imu_mono = bool(np.all(np.diff(imu_t) >= 0)) if imu_t.size > 1 else False
    lidar_mono = bool(np.all(np.diff(lidar_t) >= 0)) if lidar_t.size > 1 else False
    if not imu_mono:
        notes.append("IMU timestamps are not monotonic")
    if not lidar_mono:
        notes.append("LiDAR timestamps are not monotonic")

    imu_rate, imu_gap = _rate_and_gaps(imu_t)
    lidar_rate, lidar_gap = _rate_and_gaps(lidar_t)
    if imu_t.size < 50:
        notes.append(f"IMU sample count is low ({imu_t.size})")
    if len(frames) < 5:
        notes.append(f"LiDAR frame count is low ({len(frames)})")
    if imu_gap > 0.05:
        notes.append(f"large IMU gap detected: {imu_gap:.3f}s")
    if lidar_gap > 1.0:
        notes.append(f"large LiDAR gap detected: {lidar_gap:.3f}s")

    notes.append(
        "IMU and LiDAR clocks are treated as independent; constant offset is estimated later."
    )

    ok = imu_mono and lidar_mono and imu_t.size >= 50 and len(frames) >= 5
    return TimestampAuditReport(
        monotonic=imu_mono and lidar_mono,
        epoch_count=2,
        imu_rate_hz=imu_rate,
        lidar_rate_hz=lidar_rate,
        imu_duration_s=float(imu_t[-1] - imu_t[0]) if imu_t.size else 0.0,
        lidar_duration_s=float(lidar_t[-1] - lidar_t[0]) if lidar_t.size else 0.0,
        max_imu_gap_s=imu_gap,
        max_lidar_gap_s=lidar_gap,
        notes=tuple(notes),
        ok=ok,
    )
