"""Visual tests for tropospheric corrections using plotly charts."""

from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np
import pytest
from gri_plot.scatter import scatter
from gri_tropo.dgs import dgs_tropo_corrections
from gri_utils import conversion

if TYPE_CHECKING:
    from numpy.typing import NDArray


def _get_azim_elev_ranges() -> tuple[NDArray, NDArray]:
    # Create elevation_angles: -1 to 90 to -1 by 1's
    elevation_up = np.arange(-1, 91, 1)  # -1 to 90 inclusive
    elevation_down = np.arange(89, -2, -1)  # 89 to -1 inclusive
    elevation_angles = np.concatenate([elevation_up, elevation_down])

    # Create azimuth: first half -90, second half 90
    length = len(elevation_angles)
    azimuths = np.zeros(length)
    azimuths[: length // 2] = -90
    azimuths[length // 2 :] = 90

    return azimuths, elevation_angles


@pytest.mark.skip(reason="manual only for demonstration and test")
def test_plot_cone_correction_horizon_to_horizon() -> None:
    """Plot cone corrections from horizon to horizon.

    Creates a chart showing how tropospheric angular (cone) corrections
    vary with elevation angle from one horizon (-90°) to the opposite
    horizon (+90°), passing through zenith (90°).
    """
    # Emitter at origin (equator, prime meridian, sea level)
    emitter_loc_lla = np.array([0.0, 0.0, 0.0])
    emitter_xyz = conversion.lla_to_xyz(emitter_loc_lla)

    azimuths, elevs = _get_azim_elev_ranges()

    cone_corrections_rad = []
    cone_corrections_deg = []  # milliarcseconds

    for azim, elev in zip(azimuths, elevs, strict=True):
        collector_xyz = conversion.translate_aer(emitter_xyz, (azim, elev, 1000000))
        cone_corr, _ = dgs_tropo_corrections(emitter_loc_lla, collector_xyz)
        cone_corrections_rad.append(cone_corr)
        # Convert radians to milliarcseconds (mas)
        # 1 rad = 206264806.247 mas
        cone_corrections_deg.append(np.degrees(cone_corr))

    # Create plot
    scatter(
        (elevs, cone_corrections_deg),
        title="Tropospheric Cone Correction vs Elevation Angle",
        xaxis_title="Elevation Angle (degrees)",
        yaxis_title="Cone Correction (degrees)",
    )


@pytest.mark.skip(reason="manual only for demonstration and test")
def test_plot_time_correction_horizon_to_horizon() -> None:
    """Plot time corrections from horizon to horizon.

    Creates a chart showing how tropospheric time delay corrections
    vary with elevation angle from one horizon (-90°) to the opposite
    horizon (+90°), passing through zenith (90°).
    """
    # Emitter at origin (equator, prime meridian, sea level)
    emitter_loc_lla = np.array([0.0, 0.0, 0.0])
    emitter_xyz = conversion.lla_to_xyz(emitter_loc_lla)

    azimuths, elevs = _get_azim_elev_ranges()
    # Generate elevation angles from -90° to +90°

    time_corrections_ns = []

    for azim, elev in zip(azimuths, elevs, strict=True):
        collector_xyz = conversion.translate_aer(emitter_xyz, (azim, elev, 1000000))
        _, time_corr = dgs_tropo_corrections(emitter_loc_lla, collector_xyz)
        time_corrections_ns.append(time_corr * 1e9)

    # Create plot
    scatter(
        (elevs, time_corrections_ns),
        title="Tropospheric Time Correction vs Elevation Angle",
        xaxis_title="Elevation Angle (degrees)",
        yaxis_title="Time Correction (nanoseconds)",
    )


@pytest.mark.skip(reason="manual only for demonstration and test")
def test_plot_both_corrections_combined() -> None:
    """Plot both cone and time corrections on separate subplots.

    Creates a figure with two subplots showing both tropospheric
    corrections from horizon to horizon.
    """
    # Emitter at origin (equator, prime meridian, sea level)
    emitter_loc_lla = np.array([0.0, 0.0, 0.0])
    emitter_xyz = conversion.lla_to_xyz(emitter_loc_lla)

    azimuths, elevs = _get_azim_elev_ranges()
    # Generate elevation angles from -90° to +90°

    cone_corrections_deg = []
    time_corrections_ns = []

    for azim, elev in zip(azimuths, elevs, strict=True):
        collector_xyz = conversion.translate_aer(emitter_xyz, (azim, elev, 1000000))
        cone_corr, time_corr = dgs_tropo_corrections(emitter_loc_lla, collector_xyz)
        # Convert radians to milliarcseconds
        cone_corrections_deg.append(np.degrees(cone_corr))
        time_corrections_ns.append(time_corr * 1e9)

    # Create two separate plots
    scatter(
        (elevs, cone_corrections_deg, {"name": "Cone Correction"}),
        (
            elevs,
            time_corrections_ns,
            {"name": "Time Correction", "yaxis": "y2"},
        ),
        title="Tropospheric Corrections vs Elevation Angle",
        xaxis_title="Elevation Angle (degrees)",
        yaxis_title="Cone Correction (degrees)",
        yaxis2={"title": "Time Correction (ns)", "overlaying": "y", "side": "right"},
        yaxis_type="log",
        yaxis2_type="log",
    )
