"""Tests for Python bindings - core data models"""

import pytest
import json
import briefcase_ai


class TestInput:
    def test_input_creation(self):
        """Test Input creation and basic functionality"""
        input_obj = briefcase_ai.Input("test_input", "hello world", "string")

        assert input_obj.name == "test_input"
        assert input_obj.value == "hello world"
        assert input_obj.data_type == "string"

    def test_input_with_json_value(self):
        """Test Input with complex JSON value"""
        json_data = {"key": "value", "number": 42}
        input_obj = briefcase_ai.Input("json_input", json_data, "object")

        assert input_obj.name == "json_input"
        assert input_obj.value == json_data
        assert input_obj.data_type == "object"

    def test_input_to_object(self):
        """Test Input serialization to object"""
        input_obj = briefcase_ai.Input("test", "value", "string")
        obj = input_obj.to_object()

        assert "name" in obj
        assert "value" in obj
        assert "data_type" in obj
        assert obj["name"] == "test"


class TestOutput:
    def test_output_creation(self):
        """Test Output creation and basic functionality"""
        output_obj = briefcase_ai.Output("test_output", "result", "string")

        assert output_obj.name == "test_output"
        assert output_obj.value == "result"
        assert output_obj.data_type == "string"
        assert output_obj.confidence is None

    def test_output_with_confidence(self):
        """Test Output with confidence score"""
        output_obj = briefcase_ai.Output("test", "result", "string")
        output_obj.with_confidence(0.95)

        assert output_obj.confidence == 0.95

    def test_output_to_object_with_confidence(self):
        """Test Output serialization with confidence"""
        output_obj = briefcase_ai.Output("test", "result", "string")
        output_obj.with_confidence(0.85)

        obj = output_obj.to_object()
        assert "confidence" in obj
        assert obj["confidence"] == 0.85


class TestModelParameters:
    def test_model_parameters_creation(self):
        """Test ModelParameters creation"""
        params = briefcase_ai.ModelParameters("gpt-4")

        assert params.model_name == "gpt-4"
        assert params.provider is None

    def test_model_parameters_with_provider(self):
        """Test ModelParameters with provider"""
        params = briefcase_ai.ModelParameters("claude-3")
        params.with_provider("anthropic")

        assert params.provider == "anthropic"

    def test_model_parameters_with_parameters(self):
        """Test ModelParameters with custom parameters"""
        params = briefcase_ai.ModelParameters("gpt-4")
        params.with_parameter("temperature", 0.7)
        params.with_parameter("max_tokens", 1000)

        parameters = params.parameters
        assert "temperature" in parameters
        assert "max_tokens" in parameters
        assert parameters["temperature"] == 0.7


class TestDecisionSnapshot:
    def test_decision_snapshot_creation(self):
        """Test DecisionSnapshot creation"""
        snapshot = briefcase_ai.DecisionSnapshot("my_function")

        assert snapshot.function_name == "my_function"
        assert snapshot.module_name is None
        assert snapshot.execution_time_ms is None

    def test_decision_snapshot_with_module(self):
        """Test DecisionSnapshot with module"""
        snapshot = briefcase_ai.DecisionSnapshot("my_function")
        snapshot.with_module("my_module")

        assert snapshot.module_name == "my_module"

    def test_decision_snapshot_with_inputs_outputs(self):
        """Test DecisionSnapshot with inputs and outputs"""
        snapshot = briefcase_ai.DecisionSnapshot("classify")

        input_obj = briefcase_ai.Input("text", "hello", "string")
        output_obj = briefcase_ai.Output("label", "greeting", "string")

        snapshot.add_input(input_obj)
        snapshot.add_output(output_obj)

        # Test that the snapshot contains the data
        obj = snapshot.to_object()
        assert "function_name" in obj
        assert obj["function_name"] == "classify"

    def test_decision_snapshot_with_model_parameters(self):
        """Test DecisionSnapshot with model parameters"""
        snapshot = briefcase_ai.DecisionSnapshot("generate")
        params = briefcase_ai.ModelParameters("gpt-4")
        params.with_parameter("temperature", 0.5)

        snapshot.with_model_parameters(params)

        obj = snapshot.to_object()
        assert "model_parameters" in obj

    def test_decision_snapshot_with_execution_time(self):
        """Test DecisionSnapshot with execution time"""
        snapshot = briefcase_ai.DecisionSnapshot("my_function")
        snapshot.with_execution_time(123.45)

        assert snapshot.execution_time_ms == 123.45

    def test_decision_snapshot_with_tags(self):
        """Test DecisionSnapshot with tags"""
        snapshot = briefcase_ai.DecisionSnapshot("my_function")
        snapshot.add_tag("environment", "production")
        snapshot.add_tag("version", "1.0.0")

        tags = snapshot.tags
        assert "environment" in tags
        assert "version" in tags
        assert tags["environment"] == "production"


class TestSnapshot:
    def test_snapshot_creation(self):
        """Test Snapshot creation"""
        snapshot = briefcase_ai.Snapshot("session")

        assert snapshot.snapshot_type == "session"
        assert snapshot.decision_count == 0

    def test_snapshot_with_invalid_type(self):
        """Test Snapshot with invalid type"""
        with pytest.raises(Exception):
            briefcase_ai.Snapshot("invalid_type")

    def test_snapshot_add_decision(self):
        """Test adding decisions to snapshot"""
        snapshot = briefcase_ai.Snapshot("batch")
        decision = briefcase_ai.DecisionSnapshot("test_func")

        snapshot.add_decision(decision)

        assert snapshot.decision_count == 1

    def test_snapshot_multiple_decisions(self):
        """Test adding multiple decisions"""
        snapshot = briefcase_ai.Snapshot("batch")

        for i in range(5):
            decision = briefcase_ai.DecisionSnapshot(f"func_{i}")
            snapshot.add_decision(decision)

        assert snapshot.decision_count == 5

    def test_snapshot_to_object(self):
        """Test Snapshot serialization"""
        snapshot = briefcase_ai.Snapshot("decision")
        decision = briefcase_ai.DecisionSnapshot("my_func")
        snapshot.add_decision(decision)

        obj = snapshot.to_object()
        assert "snapshot_type" in obj
        assert "decisions" in obj


class TestIntegration:
    def test_complete_workflow(self):
        """Test a complete AI decision workflow"""
        # Create a decision snapshot
        decision = briefcase_ai.DecisionSnapshot("text_classification")
        decision.with_module("nlp_service")

        # Add input
        input_text = briefcase_ai.Input("text", "This is a great product!", "string")
        decision.add_input(input_text)

        # Add model parameters
        params = briefcase_ai.ModelParameters("bert-base-uncased")
        params.with_provider("huggingface")
        params.with_parameter("max_length", 512)
        decision.with_model_parameters(params)

        # Add output
        output_label = briefcase_ai.Output("sentiment", "positive", "string")
        output_label.with_confidence(0.92)
        decision.add_output(output_label)

        # Set execution time and tags
        decision.with_execution_time(45.2)
        decision.add_tag("model_version", "v2.1")
        decision.add_tag("environment", "staging")

        # Create session snapshot and add decision
        session = briefcase_ai.Snapshot("session")
        session.add_decision(decision)

        # Verify everything is captured
        assert session.decision_count == 1
        assert decision.function_name == "text_classification"
        assert decision.module_name == "nlp_service"
        assert decision.execution_time_ms == 45.2

        # Serialize to check structure
        session_obj = session.to_object()
        assert "decisions" in session_obj

        decision_obj = decision.to_object()
        assert "inputs" in decision_obj
        assert "outputs" in decision_obj
        assert "model_parameters" in decision_obj
        assert "tags" in decision_obj


if __name__ == "__main__":
    pytest.main([__file__])