"""Tests for InterviewPresenter classes."""

import pytest

from optimization_engine.interview.interview_presenter import (
    InterviewPresenter,
    ClaudePresenter,
    DashboardPresenter,
    CLIPresenter,
)
from optimization_engine.interview.question_engine import Question, QuestionOption
from optimization_engine.interview.study_blueprint import (
    StudyBlueprint,
    DesignVariable,
    Objective,
    Constraint
)


class TestClaudePresenter:
    """Tests for ClaudePresenter."""

    def test_present_choice_question(self):
        """Test presenting a choice question."""
        presenter = ClaudePresenter()

        question = Question(
            id="obj_01",
            category="objectives",
            text="What is your primary optimization goal?",
            question_type="choice",
            maps_to="objectives[0].goal",
            options=[
                QuestionOption(value="minimize_mass", label="Minimize mass/weight"),
                QuestionOption(value="minimize_displacement", label="Minimize displacement"),
            ],
            help_text="Choose what you want to optimize for."
        )

        result = presenter.present_question(
            question,
            question_number=1,
            total_questions=10,
            category_name="Objectives"
        )

        assert "1" in result  # Question number
        assert "10" in result  # Total
        assert "What is your primary optimization goal?" in result
        assert "Minimize mass/weight" in result

    def test_present_numeric_question(self):
        """Test presenting a numeric question."""
        presenter = ClaudePresenter()

        question = Question(
            id="con_01",
            category="constraints",
            text="What is the maximum allowable stress (MPa)?",
            question_type="numeric",
            maps_to="constraints[0].threshold"
        )

        result = presenter.present_question(
            question,
            question_number=3,
            total_questions=8,
            category_name="Constraints"
        )

        assert "maximum allowable stress" in result

    def test_present_text_question(self):
        """Test presenting a text question."""
        presenter = ClaudePresenter()

        question = Question(
            id="pd_01",
            category="problem_definition",
            text="Describe your study in a few words.",
            question_type="text",
            maps_to="study_description"
        )

        result = presenter.present_question(
            question,
            question_number=1,
            total_questions=10,
            category_name="Problem Definition"
        )

        assert "Describe your study" in result

    def test_present_confirm_question(self):
        """Test presenting a confirmation question."""
        presenter = ClaudePresenter()

        question = Question(
            id="val_01",
            category="validation",
            text="Would you like to run a baseline validation?",
            question_type="confirm",
            maps_to="run_baseline"
        )

        result = presenter.present_question(
            question,
            question_number=8,
            total_questions=8,
            category_name="Validation"
        )

        assert "baseline validation" in result

    def test_parse_choice_response_by_number(self):
        """Test parsing choice response by number."""
        presenter = ClaudePresenter()

        question = Question(
            id="obj_01",
            category="objectives",
            text="Choose goal",
            question_type="choice",
            maps_to="objective",
            options=[
                QuestionOption(value="minimize_mass", label="Minimize mass"),
                QuestionOption(value="minimize_stress", label="Minimize stress"),
            ]
        )

        result = presenter.parse_response("1", question)
        assert result == "minimize_mass"

        result = presenter.parse_response("2", question)
        assert result == "minimize_stress"

    def test_parse_numeric_response(self):
        """Test parsing numeric response."""
        presenter = ClaudePresenter()

        question = Question(
            id="con_01",
            category="constraints",
            text="Max stress?",
            question_type="numeric",
            maps_to="threshold"
        )

        result = presenter.parse_response("200", question)
        assert result == 200.0

        result = presenter.parse_response("about 150 MPa", question)
        assert result == 150.0

    def test_parse_confirm_response(self):
        """Test parsing confirmation response."""
        presenter = ClaudePresenter()

        question = Question(
            id="val_01",
            category="validation",
            text="Run validation?",
            question_type="confirm",
            maps_to="run_baseline"
        )

        # Various ways to say yes
        assert presenter.parse_response("yes", question) is True
        assert presenter.parse_response("Yeah", question) is True
        assert presenter.parse_response("y", question) is True

        # Various ways to say no
        assert presenter.parse_response("no", question) is False
        assert presenter.parse_response("Nope", question) is False
        assert presenter.parse_response("n", question) is False

    def test_show_progress(self):
        """Test showing progress."""
        presenter = ClaudePresenter()

        result = presenter.show_progress(5, 10, "Objectives")
        assert "5" in result or "50%" in result  # May show percentage instead
        assert "Objectives" in result

    def test_show_summary(self):
        """Test showing blueprint summary."""
        presenter = ClaudePresenter()

        blueprint = StudyBlueprint(
            study_name="test_study",
            study_description="A test study",
            model_path="/path/to/model.prt",
            sim_path="/path/to/sim.sim",
            design_variables=[
                DesignVariable(parameter="thickness", current_value=5.0, min_value=1.0, max_value=10.0)
            ],
            objectives=[
                Objective(name="mass", goal="minimize", extractor="E4")
            ],
            constraints=[
                Constraint(name="stress", constraint_type="max", threshold=200, extractor="E3")
            ],
            protocol="protocol_10_single",
            n_trials=100,
            sampler="TPE"
        )

        result = presenter.show_summary(blueprint)

        assert "test_study" in result
        assert "thickness" in result

    def test_show_warning(self):
        """Test showing warning."""
        presenter = ClaudePresenter()

        result = presenter.show_warning("Stress limit is close to yield")
        assert "yield" in result


class TestDashboardPresenter:
    """Tests for DashboardPresenter."""

    def test_present_question_returns_structured_data(self):
        """Test that dashboard presenter returns structured data."""
        presenter = DashboardPresenter()

        question = Question(
            id="obj_01",
            category="objectives",
            text="What is your goal?",
            question_type="choice",
            maps_to="objective",
            options=[QuestionOption(value="mass", label="Minimize mass")]
        )

        result = presenter.present_question(
            question,
            question_number=1,
            total_questions=10,
            category_name="Objectives"
        )

        # Dashboard presenter may return nested structure
        import json
        if isinstance(result, str):
            data = json.loads(result)
        else:
            data = result

        # Check for question data (may be nested in 'data' key)
        if "data" in data:
            assert "question_id" in data["data"]
            assert "text" in data["data"]
        else:
            assert "question_id" in data
            assert "text" in data


class TestCLIPresenter:
    """Tests for CLIPresenter."""

    def test_present_question_plain_text(self):
        """Test CLI presenter uses plain text."""
        presenter = CLIPresenter()

        question = Question(
            id="obj_01",
            category="objectives",
            text="What is your goal?",
            question_type="choice",
            maps_to="objective",
            options=[
                QuestionOption(value="mass", label="Minimize mass"),
                QuestionOption(value="stress", label="Minimize stress")
            ]
        )

        result = presenter.present_question(
            question,
            question_number=1,
            total_questions=10,
            category_name="Objectives"
        )

        assert "What is your goal?" in result

