"""Integration tests for StudyInterviewEngine."""

import pytest
import tempfile
from pathlib import Path

from optimization_engine.interview.study_interview import (
    StudyInterviewEngine,
    InterviewSession,
    NextAction,
    run_interview,
)
from optimization_engine.interview.interview_state import InterviewState, InterviewPhase


class TestInterviewSession:
    """Tests for InterviewSession dataclass."""

    def test_creation(self):
        """Test creating interview session."""
        from datetime import datetime

        session = InterviewSession(
            session_id="abc123",
            study_name="test_study",
            study_path=Path("/tmp/test"),
            started_at=datetime.now(),
            current_phase=InterviewPhase.INTROSPECTION,
            introspection={}
        )

        assert session.session_id == "abc123"
        assert session.study_name == "test_study"
        assert not session.is_complete


class TestNextAction:
    """Tests for NextAction dataclass."""

    def test_ask_question_action(self):
        """Test ask_question action type."""
        from optimization_engine.interview.question_engine import Question

        question = Question(
            id="test",
            category="test",
            text="Test?",
            question_type="text",
            maps_to="test_field"
        )

        action = NextAction(
            action_type="ask_question",
            question=question,
            message="Test question"
        )

        assert action.action_type == "ask_question"
        assert action.question is not None

    def test_show_summary_action(self):
        """Test show_summary action type."""
        action = NextAction(
            action_type="show_summary",
            message="Summary here"
        )

        assert action.action_type == "show_summary"

    def test_error_action(self):
        """Test error action type."""
        action = NextAction(
            action_type="error",
            message="Something went wrong"
        )

        assert action.action_type == "error"
        assert "wrong" in action.message


class TestStudyInterviewEngine:
    """Tests for StudyInterviewEngine."""

    def test_init(self):
        """Test engine initialization."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)

            assert engine.study_path == study_path
            assert engine.state is None
            assert engine.presenter is not None

    def test_start_interview_new(self):
        """Test starting a new interview."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            session = engine.start_interview("test_study")

            assert session is not None
            assert session.study_name == "test_study"
            assert not session.is_resumed
            assert engine.state is not None

    def test_start_interview_with_introspection(self):
        """Test starting interview with introspection data."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)

            introspection = {
                "expressions": ["thickness", "width"],
                "model_path": "/path/model.prt",
                "sim_path": "/path/sim.sim"
            }

            session = engine.start_interview(
                "test_study",
                introspection=introspection
            )

            assert session.introspection == introspection
            # Should skip introspection phase
            assert engine.state.get_phase() == InterviewPhase.PROBLEM_DEFINITION

    def test_start_interview_resume(self):
        """Test resuming an existing interview."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            # Start first interview
            engine1 = StudyInterviewEngine(study_path)
            session1 = engine1.start_interview("test_study")

            # Make some progress
            engine1.state.answers["study_description"] = "Test"
            engine1.state.set_phase(InterviewPhase.OBJECTIVES)
            engine1.state_manager.save_state(engine1.state)

            # Create new engine and resume
            engine2 = StudyInterviewEngine(study_path)
            session2 = engine2.start_interview("test_study")

            assert session2.is_resumed
            assert engine2.state.get_phase() == InterviewPhase.OBJECTIVES

    def test_get_first_question(self):
        """Test getting first question."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={"expressions": []})

            action = engine.get_first_question()

            assert action.action_type == "ask_question"
            assert action.question is not None
            assert action.message is not None

    def test_get_first_question_without_start(self):
        """Test error when getting question without starting."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)

            action = engine.get_first_question()

            assert action.action_type == "error"

    def test_process_answer(self):
        """Test processing an answer."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})

            # Get first question
            action = engine.get_first_question()
            assert action.question is not None

            # Answer it
            next_action = engine.process_answer("This is my test study description")

            # May get next question, show summary, error, or confirm_warning
            assert next_action.action_type in ["ask_question", "show_summary", "error", "confirm_warning"]

    def test_process_answer_invalid(self):
        """Test processing an invalid answer."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})
            engine.get_first_question()

            # For a required question, empty answer should fail
            # This depends on question validation rules
            # Just verify we don't crash
            action = engine.process_answer("")
            assert action.action_type in ["error", "ask_question"]

    def test_full_simple_interview_flow(self):
        """Test complete simple interview flow."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={
                "expressions": [
                    {"name": "thickness", "value": 5.0},
                    {"name": "width", "value": 10.0}
                ],
                "model_path": "/model.prt",
                "sim_path": "/sim.sim"
            })

            # Simulate answering questions
            answers = [
                "Bracket mass optimization",  # study description
                "minimize mass",  # objective
                "1",  # single objective confirm
                "stress, 200 MPa",  # constraint
                "thickness, width",  # design variables
                "yes",  # confirm settings
            ]

            action = engine.get_first_question()
            max_iterations = 20

            for i, answer in enumerate(answers):
                if action.action_type == "show_summary":
                    break
                if action.action_type == "error":
                    # Try to recover
                    continue

                action = engine.process_answer(answer)

                if i > max_iterations:
                    break

            # Should eventually complete or show summary
            # (exact behavior depends on question flow)

    def test_acknowledge_warnings(self):
        """Test acknowledging warnings."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})

            # Add some warnings
            engine.state.add_warning("Test warning 1")
            engine.state.add_warning("Test warning 2")

            action = engine.acknowledge_warnings(acknowledged=True)

            # Warnings should be acknowledged
            assert "Test warning 1" in engine.state.warnings_acknowledged
            assert "Test warning 2" in engine.state.warnings_acknowledged

    def test_acknowledge_warnings_rejected(self):
        """Test rejecting warnings pauses interview."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})
            engine.state.add_warning("Test warning")

            action = engine.acknowledge_warnings(acknowledged=False)

            assert action.action_type == "error"

    def test_generate_blueprint(self):
        """Test blueprint generation."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={
                "model_path": "/model.prt",
                "sim_path": "/sim.sim"
            })

            # Set up minimal answers for blueprint
            engine.state.answers = {
                "study_description": "Test",
                "objectives": [{"goal": "minimize_mass"}],
                "constraints": [{"type": "stress", "threshold": 200}],
                "design_variables": [{"name": "t", "min": 1, "max": 10}],
            }

            blueprint = engine.generate_blueprint()

            assert blueprint is not None
            assert blueprint.study_name == "test_study"
            assert len(blueprint.objectives) == 1

    def test_modify_blueprint(self):
        """Test blueprint modification."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})

            # Set up and generate blueprint
            engine.state.answers = {
                "study_description": "Test",
                "objectives": [{"goal": "minimize_mass"}],
                "constraints": [],
                "design_variables": [{"name": "t", "min": 1, "max": 10}],
            }
            engine.generate_blueprint()

            # Modify n_trials
            modified = engine.modify_blueprint({"n_trials": 200})

            assert modified.n_trials == 200

    def test_confirm_blueprint(self):
        """Test confirming blueprint."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})

            engine.state.answers = {
                "study_description": "Test",
                "objectives": [{"goal": "minimize_mass"}],
                "constraints": [],
                "design_variables": [{"name": "t", "min": 1, "max": 10}],
            }
            engine.generate_blueprint()

            result = engine.confirm_blueprint()

            assert result is True
            assert engine.state.get_phase() == InterviewPhase.COMPLETE

    def test_get_progress(self):
        """Test getting progress string."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})

            progress = engine.get_progress()

            assert isinstance(progress, str)
            assert len(progress) > 0

    def test_reset_interview(self):
        """Test resetting interview."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)
            engine.start_interview("test_study", introspection={})

            # Make some progress
            engine.state.answers["test"] = "value"

            engine.reset_interview()

            assert engine.state is None
            assert engine.session is None

    def test_get_current_state(self):
        """Test getting current state."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = StudyInterviewEngine(study_path)

            assert engine.get_current_state() is None

            engine.start_interview("test_study", introspection={})

            state = engine.get_current_state()
            assert state is not None
            assert state.study_name == "test_study"


class TestRunInterview:
    """Tests for run_interview convenience function."""

    def test_run_interview(self):
        """Test run_interview function."""
        with tempfile.TemporaryDirectory() as tmpdir:
            study_path = Path(tmpdir) / "test_study"
            study_path.mkdir()

            engine = run_interview(
                study_path,
                "test_study",
                introspection={"expressions": []}
            )

            assert engine is not None
            assert engine.state is not None
            assert engine.session is not None

