"""Helpers for building stable TLE lines from orbital elements."""

from __future__ import annotations

from datetime import datetime
from typing import Any, Optional


def compute_tle_checksum(line: str) -> str:
    """Compute the standard modulo-10 checksum for a TLE line."""
    total = 0

    for char in line[:68]:
        if char.isdigit():
            total += int(char)
        elif char == "-":
            total += 1

    return str(total % 10)


def _parse_epoch(value: Any) -> Optional[datetime]:
    if not value:
        return None
    if isinstance(value, datetime):
        return value
    if isinstance(value, str):
        return datetime.fromisoformat(value.replace("Z", "+00:00"))
    return None


def build_tle_line1(norad_cat_id: Any, epoch: Any) -> Optional[str]:
    """Build a valid TLE line 1 from the NORAD id and epoch."""
    epoch_date = _parse_epoch(epoch)
    if not norad_cat_id or epoch_date is None:
        return None

    epoch_year = epoch_date.year % 100
    start_of_year = datetime(epoch_date.year, 1, 1, tzinfo=epoch_date.tzinfo)
    day_of_year = (epoch_date - start_of_year).days + 1
    ms_of_day = (
        epoch_date.hour * 3600000
        + epoch_date.minute * 60000
        + epoch_date.second * 1000
        + int(epoch_date.microsecond / 1000)
    )
    day_fraction = ms_of_day / 86400000
    decimal_fraction = f"{day_fraction:.8f}"[1:]
    epoch_str = f"{epoch_year:02d}{day_of_year:03d}{decimal_fraction}"

    core = (
        f"1 {int(norad_cat_id):05d}U 00001A   {epoch_str}"
        "  .00000000  00000-0  00000-0 0  999"
    )
    return core + compute_tle_checksum(core)


def build_tle_line2(
    norad_cat_id: Any,
    inclination: Any,
    raan: Any,
    eccentricity: Any,
    arg_of_perigee: Any,
    mean_anomaly: Any,
    mean_motion: Any,
) -> Optional[str]:
    """Build a valid TLE line 2 from the standard orbital elements."""
    required = [
        norad_cat_id,
        inclination,
        raan,
        eccentricity,
        arg_of_perigee,
        mean_anomaly,
        mean_motion,
    ]
    if any(value is None for value in required):
        return None

    eccentricity_digits = str(round(float(eccentricity) * 10_000_000)).zfill(7)
    core = (
        f"2 {int(norad_cat_id):05d}"
        f" {float(inclination):8.4f}"
        f" {float(raan):8.4f}"
        f" {eccentricity_digits}"
        f" {float(arg_of_perigee):8.4f}"
        f" {float(mean_anomaly):8.4f}"
        f" {float(mean_motion):11.8f}"
        "00000"
    )
    return core + compute_tle_checksum(core)


def build_tle_lines_from_elements(
    *,
    norad_cat_id: Any,
    epoch: Any,
    inclination: Any,
    raan: Any,
    eccentricity: Any,
    arg_of_perigee: Any,
    mean_anomaly: Any,
    mean_motion: Any,
) -> tuple[Optional[str], Optional[str]]:
    """Build both TLE lines from a metadata payload."""
    line1 = build_tle_line1(norad_cat_id, epoch)
    line2 = build_tle_line2(
        norad_cat_id,
        inclination,
        raan,
        eccentricity,
        arg_of_perigee,
        mean_anomaly,
        mean_motion,
    )
    return line1, line2
