"""
Tests for the CLI orchestrator.
"""
import sys
import argparse
from unittest.mock import patch, MagicMock

import pytest

# Import the run module's functions
from run import validate_args, run_lessons_pipeline, run_roadmap_pipeline


def test_validate_args_valid_lessons():
    """Test validating valid lessons pipeline arguments."""
    # Create a valid lessons pipeline args object
    args = argparse.Namespace(
        pipeline="lessons",
        step="extract_topics",
        id="test-run",
        pdf="input/test.pdf",
        force_text=False,
        track_id=None,
        path_id=None,
        step_id=None
    )

    # This should not raise an exception
    validate_args(args)


def test_validate_args_valid_roadmap():
    """Test validating valid roadmap pipeline arguments."""
    # Create a valid roadmap pipeline args object
    args = argparse.Namespace(
        pipeline="roadmap",
        step="tracks",
        id="test-run",
        pdf=None,
        force_text=False,
        track_id=None,
        path_id=None,
        step_id=None
    )

    # This should not raise an exception
    validate_args(args)


def test_validate_args_invalid_pipeline():
    """Test validating an invalid pipeline."""
    # Create an args object with an invalid pipeline
    args = argparse.Namespace(
        pipeline="invalid",
        step="extract_topics",
        id="test-run",
        pdf="input/test.pdf",
        force_text=False,
        track_id=None,
        path_id=None,
        step_id=None
    )

    # This should raise a ValueError
    with pytest.raises(ValueError):
        validate_args(args)


def test_validate_args_invalid_step():
    """Test validating an invalid step."""
    # Create an args object with an invalid step
    args = argparse.Namespace(
        pipeline="lessons",
        step="invalid",
        id="test-run",
        pdf="input/test.pdf",
        force_text=False,
        track_id=None,
        path_id=None,
        step_id=None
    )

    # This should raise a ValueError
    with pytest.raises(ValueError):
        validate_args(args)


def test_validate_args_missing_pdf():
    """Test validating args with missing PDF for extract_topics."""
    # Mock load_latest_output to return None (no existing output)
    with patch("utils.io.load_latest_output", return_value=None):
        # Create an args object with missing PDF
        args = argparse.Namespace(
            pipeline="lessons",
            step="extract_topics",
            id="test-run",
            pdf=None,
            force_text=False,
            track_id=None,
            path_id=None,
            step_id=None
        )

        # This should raise a ValueError
        with pytest.raises(ValueError):
            validate_args(args)


def test_validate_args_existing_output():
    """Test validating args with existing output for extract_topics."""
    # Mock load_latest_output to return some data (existing output)
    with patch("utils.io.load_latest_output", return_value="Some output"):
        # Create an args object with missing PDF but existing output
        args = argparse.Namespace(
            pipeline="lessons",
            step="extract_topics",
            id="test-run",
            pdf=None,
            force_text=True,
            track_id=None,
            path_id=None,
            step_id=None
        )

        # This should not raise an exception
        validate_args(args)


@patch("chains.lessons.extract_topics.extract_topics_from_pdf")
def test_run_lessons_pipeline_extract_topics(mock_extract):
    """Test running the lessons pipeline for extract_topics."""
    # Mock extract_topics_from_pdf to return a dictionary with a root list
    mock_extract.return_value = {"root": [{"topic": "Test Topic"}]}

    # Create args for extract_topics
    args = argparse.Namespace(
        pipeline="lessons",
        step="extract_topics",
        id="test-run",
        pdf="input/test.pdf",
        force_text=False,
        track_id=None,
        path_id=None,
        step_id=None
    )

    # Run the pipeline
    run_lessons_pipeline(args)

    # Check that extract_topics_from_pdf was called with the correct arguments
    mock_extract.assert_called_once_with(
        pdf_path="input/test.pdf",
        run_id="test-run",
        force_text=False
    )


@patch("chains.roadmap.tracks.generate_tracks")
def test_run_roadmap_pipeline_tracks(mock_generate):
    """Test running the roadmap pipeline for tracks."""
    # Mock generate_tracks to return a dictionary with a tracks list
    mock_generate.return_value = {"tracks": [{"id": "test-track"}]}

    # Create args for tracks
    args = argparse.Namespace(
        pipeline="roadmap",
        step="tracks",
        id="test-run",
        pdf=None,
        force_text=False,
        track_id=None,
        path_id=None,
        step_id=None
    )

    # Run the pipeline
    run_roadmap_pipeline(args)

    # Check that generate_tracks was called with the correct arguments
    mock_generate.assert_called_once_with(
        run_id="test-run",
        force_text=False
    )