"""
State management tests for Response API.

Tests both previous_response_id and conversation-based state management.
These tests should work across all backends (OpenAI, XAI, gRPC).
"""

import unittest

from basic_crud import ResponseAPIBaseTest


class StateManagementTests(ResponseAPIBaseTest):
    """Tests for state management using previous_response_id and conversation."""

    def test_previous_response_id_chaining(self):
        """Test chaining responses using previous_response_id."""
        # First response
        resp1 = self.create_response(
            "My name is Alice and my friend is Bob. Remember it."
        )
        self.assertEqual(resp1.status_code, 200)
        response1_id = resp1.json()["id"]

        # Second response referencing first
        resp2 = self.create_response(
            "What is my name", previous_response_id=response1_id
        )
        self.assertEqual(resp2.status_code, 200)
        response2_data = resp2.json()

        # The model should remember the name from previous response
        output_text = self._extract_output_text(response2_data)
        self.assertIn("Alice", output_text)

        # Third response referencing second
        resp3 = self.create_response(
            "What is my friend name?",
            previous_response_id=response2_data["id"],
        )
        response3_data = resp3.json()
        output_text = self._extract_output_text(response3_data)
        self.assertEqual(resp3.status_code, 200)
        self.assertIn("Bob", output_text)

    @unittest.skip("TODO: Add the invalid previous_response_id check")
    def test_previous_response_id_invalid(self):
        """Test using invalid previous_response_id."""
        resp = self.create_response(
            "Test", previous_response_id="resp_invalid123", max_output_tokens=50
        )
        self.assertIn(resp.status_code, [400, 404])

    def test_conversation_with_multiple_turns(self):
        """Test state management using conversation ID."""
        # Create conversation
        conv_resp = self.create_conversation(metadata={"topic": "math"})
        self.assertEqual(conv_resp.status_code, 200)

        conversation_id = conv_resp.json()["id"]

        # First response in conversation
        resp1 = self.create_response("I have 5 apples.", conversation=conversation_id)
        self.assertEqual(resp1.status_code, 200)

        # Second response in same conversation
        resp2 = self.create_response(
            "How many apples do I have?",
            conversation=conversation_id,
        )
        self.assertEqual(resp2.status_code, 200)
        output_text = self._extract_output_text(resp2.json())

        # Should remember "5 apples"
        self.assertTrue("5" in output_text or "five" in output_text.lower())

        # Third response in same conversation
        resp3 = self.create_response(
            "If I get 3 more, how many total?",
            conversation=conversation_id,
        )
        self.assertEqual(resp3.status_code, 200)
        output_text = self._extract_output_text(resp3.json())

        # Should calculate 5 + 3 = 8
        self.assertTrue("8" in output_text or "eight" in output_text.lower())
        list_resp = self.list_conversation_items(conversation_id)
        self.assertEqual(list_resp.status_code, 200)
        items = list_resp.json()["data"]
        # Should have at least 6 items (3 inputs + 3 outputs)
        self.assertGreaterEqual(len(items), 6)

    def test_mutually_exclusive_parameters(self):
        """Test that previous_response_id and conversation are mutually exclusive."""
        # Create conversation and response
        conv_resp = self.create_conversation()
        conversation_id = conv_resp.json()["id"]

        resp1 = self.create_response("Test")
        response1_id = resp1.json()["id"]

        # Try to use both parameters
        resp = self.create_response(
            "This should fail",
            previous_response_id=response1_id,
            conversation=conversation_id,
        )

        # Should return 400 Bad Request
        self.assertEqual(resp.status_code, 400)
        error_data = resp.json()
        self.assertIn("error", error_data)
        self.assertIn("mutually exclusive", error_data["error"]["message"].lower())

    # Helper methods

    def _extract_output_text(self, response_data: dict) -> str:
        """Extract text content from response output."""
        output = response_data.get("output", [])
        if not output:
            return ""

        text_parts = []
        for item in output:
            content = item.get("content", [])
            for part in content:
                if part.get("type") == "output_text":
                    text_parts.append(part.get("text", ""))

        return " ".join(text_parts)
