"""Create OrbitalElements from a state vector (position, velocity).

This module provides a convenient function to create orbital elements from
an OrbitState at a given time. It is essentially an alias for state_to_elements
but named to match the from_* convention of other orbit creation functions.

References:
    - Vallado, D. "Fundamentals of Astrodynamics and Applications", 4th ed.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np

from .orbit_state import OrbitState
from .state_to_elements import state_to_elements

if TYPE_CHECKING:
    from numpy.typing import NDArray

    from .orbital_elements import OrbitalElements


def from_state(
    state: OrbitState,
    unix_s: float,
) -> OrbitalElements:
    """Create OrbitalElements from a state vector at a given time.

    Computes classical Keplerian orbital elements from position and velocity
    vectors. This is a convenience alias for state_to_elements().

    Args:
        state: OrbitState containing position and velocity in ECI frame.
            The acceleration component is not used.
        unix_s: Time of the state as Unix timestamp in seconds. This becomes
            the epoch of the resulting orbital elements.

    Returns:
        OrbitalElements representing the orbit.

    Raises:
        ValueError: If the orbit is parabolic/hyperbolic (e >= 1) or if the
            state represents a degenerate case.

    Example:
        >>> import numpy as np
        >>> from gri_utils.orbit import OrbitState, from_state
        >>> state = OrbitState(
        ...     position_eci_m=np.array([7_000_000.0, 0.0, 0.0]),
        ...     velocity_eci_ms=np.array([0.0, 7546.0, 0.0]),
        ...     acceleration_eci_ms2=np.array([0.0, 0.0, 0.0]),
        ... )
        >>> elements = from_state(state, unix_s=1704067200.0)
    """
    return state_to_elements(state, unix_s)


def from_position_velocity(
    position_eci_m: NDArray[np.floating],
    velocity_eci_ms: NDArray[np.floating],
    unix_s: float,
) -> OrbitalElements:
    """Create OrbitalElements from position and velocity vectors.

    Convenience function that creates an OrbitState internally.

    Args:
        position_eci_m: Position vector in ECI frame, meters. Shape (3,).
        velocity_eci_ms: Velocity vector in ECI frame, m/s. Shape (3,).
        unix_s: Time of the state as Unix timestamp in seconds.

    Returns:
        OrbitalElements representing the orbit.

    Example:
        >>> import numpy as np
        >>> from gri_utils.orbit import from_position_velocity
        >>> elements = from_position_velocity(
        ...     position_eci_m=np.array([7_000_000.0, 0.0, 0.0]),
        ...     velocity_eci_ms=np.array([0.0, 7546.0, 0.0]),
        ...     unix_s=1704067200.0,
        ... )
    """
    state = OrbitState(
        position_eci_m=np.asarray(position_eci_m),
        velocity_eci_ms=np.asarray(velocity_eci_ms),
        acceleration_eci_ms2=np.zeros(3),
    )
    return state_to_elements(state, unix_s)
