"""Tests for conversation validator dispatch and transcript correction."""

import pytest
from unittest.mock import patch, MagicMock
from conftest import MockSession, MockLLM

from qwen_pipeline_server import PipelineSession


class TestCorrectTranscript:
    """Tests for PipelineSession._correct_transcript()."""

    def test_corrected_lines_parsed(self):
        log = [
            {'speaker': 'caller', 'text': 'Tell me about Enfos'},
            {'speaker': 'AI', 'text': 'mForce helps manage field teams.'},
        ]
        corrected_text = "User: Tell me about mForce\nAI: mForce helps manage field teams."
        session = MockSession(llm=MockLLM(corrected_text), llm_model='test')
        result = PipelineSession._correct_transcript(session, log)
        assert result[0]['text'] == 'Tell me about mForce'
        assert result[1]['text'] == 'mForce helps manage field teams.'

    def test_ai_lines_unchanged(self):
        log = [
            {'speaker': 'caller', 'text': 'Hello'},
            {'speaker': 'AI', 'text': 'Hi there, how can I help?'},
        ]
        corrected_text = "User: Hello\nAI: Hi there, how can I help?"
        session = MockSession(llm=MockLLM(corrected_text), llm_model='test')
        result = PipelineSession._correct_transcript(session, log)
        assert result[1]['text'] == 'Hi there, how can I help?'

    def test_llm_failure_returns_original(self):
        log = [
            {'speaker': 'caller', 'text': 'Hello'},
            {'speaker': 'AI', 'text': 'Hi'},
        ]

        class FailingLLM:
            class chat:
                class completions:
                    @staticmethod
                    def create(**kwargs):
                        raise Exception("LLM error")

        session = MockSession(llm=FailingLLM(), llm_model='test')
        result = PipelineSession._correct_transcript(session, log)
        assert result[0]['text'] == 'Hello'
        assert result[1]['text'] == 'Hi'

    def test_fewer_corrected_lines(self):
        log = [
            {'speaker': 'caller', 'text': 'Hello'},
            {'speaker': 'AI', 'text': 'Hi'},
            {'speaker': 'caller', 'text': 'Bye'},
        ]
        # LLM returns only 2 lines instead of 3
        corrected_text = "User: Hello\nAI: Hi"
        session = MockSession(llm=MockLLM(corrected_text), llm_model='test')
        result = PipelineSession._correct_transcript(session, log)
        # First two should be corrected, third keeps original
        assert result[0]['text'] == 'Hello'
        assert result[1]['text'] == 'Hi'
        assert result[2]['text'] == 'Bye'

    def test_preserves_other_fields(self):
        log = [
            {'speaker': 'caller', 'text': 'Enfos', 'timestamp': '14:00:01'},
        ]
        corrected_text = "User: mForce"
        session = MockSession(llm=MockLLM(corrected_text), llm_model='test')
        result = PipelineSession._correct_transcript(session, log)
        assert result[0]['timestamp'] == '14:00:01'
        assert result[0]['speaker'] == 'caller'


class TestDispatchToValidator:
    """Tests for PipelineSession._dispatch_to_validator()."""

    def _make_session(self, conversation_log, api_url='https://test.com/validate',
                      api_key='test-key'):
        session = MockSession(
            conversation_log=conversation_log,
            cv_api_url=api_url,
            cv_api_key=api_key,
            llm=MockLLM(''),
            llm_model='test',
        )
        # Bind _correct_transcript to return log as-is (skip LLM correction)
        session._correct_transcript = lambda log: log
        return session

    @patch('qwen_pipeline_server.requests.post')
    def test_turn_formatting(self, mock_post, sample_conversation_log):
        mock_post.return_value = MagicMock(status_code=200)
        session = self._make_session(sample_conversation_log)

        PipelineSession._dispatch_to_validator(session)

        call_args = mock_post.call_args
        payload = call_args[1]['json']
        assert 'conversation' in payload
        assert 'Turn 1:' in payload['conversation']
        assert 'User:' in payload['conversation']
        assert 'AI:' in payload['conversation']

    @patch('qwen_pipeline_server.requests.post')
    def test_api_key_in_headers(self, mock_post, sample_conversation_log):
        mock_post.return_value = MagicMock(status_code=200)
        session = self._make_session(sample_conversation_log, api_key='my-secret')

        PipelineSession._dispatch_to_validator(session)

        headers = mock_post.call_args[1]['headers']
        assert headers['X-API-KEY'] == 'my-secret'

    @patch('qwen_pipeline_server.requests.post')
    def test_no_api_key(self, mock_post, sample_conversation_log):
        mock_post.return_value = MagicMock(status_code=200)
        session = self._make_session(sample_conversation_log, api_key='')

        PipelineSession._dispatch_to_validator(session)

        headers = mock_post.call_args[1]['headers']
        assert 'X-API-KEY' not in headers

    @patch('qwen_pipeline_server.requests.post')
    def test_success_result(self, mock_post, sample_conversation_log):
        mock_post.return_value = MagicMock(status_code=200)
        session = self._make_session(sample_conversation_log)

        result = PipelineSession._dispatch_to_validator(session)

        assert result['success'] is True

    @patch('qwen_pipeline_server.requests.post')
    def test_api_error(self, mock_post, sample_conversation_log):
        mock_post.return_value = MagicMock(status_code=500, text='Internal Error')
        session = self._make_session(sample_conversation_log)

        result = PipelineSession._dispatch_to_validator(session)

        assert result['success'] is False
        assert '500' in result['message']

    @patch('qwen_pipeline_server.requests.post')
    def test_network_error(self, mock_post, sample_conversation_log):
        mock_post.side_effect = Exception('Connection refused')
        session = self._make_session(sample_conversation_log)

        result = PipelineSession._dispatch_to_validator(session)

        assert result['success'] is False
        assert 'Connection refused' in result['message']
