"""
Tests for export functionality (v0.4.0 Feature #3).

Testing ConsultationExporter and SessionExporter.
"""

import pytest
import json
from datetime import datetime
from sensei_mcp.exporter import ConsultationExporter, SessionExporter
from sensei_mcp.models import Consultation, SessionState, Decision


@pytest.fixture
def sample_consultation():
    """Create a sample consultation for testing."""
    return Consultation(
        id="test-123",
        timestamp="2025-01-22T10:00:00",
        query="How should we implement API rate limiting?",
        mode="multi-persona",
        personas_consulted=["platform-builder", "security-guardian", "pragmatic-architect"],
        context="api-design",
        synthesis="Implement token bucket algorithm with Redis backend. Use API Gateway for enforcement.",
        decision_id="dec-456"
    )


@pytest.fixture
def sample_consultation_no_decision():
    """Create a consultation without a linked decision."""
    return Consultation(
        id="test-124",
        timestamp="2025-01-22T11:00:00",
        query="Best practices for error handling?",
        mode="quick",
        personas_consulted=["pragmatic-architect"],
        context="code-quality",
        synthesis="Use structured error types and centralized error handling.",
        decision_id=None
    )


@pytest.fixture
def sample_session():
    """Create a sample session for testing."""
    decisions = [
        Decision(
            id="dec-1",
            category="architecture",
            description="Use microservices architecture",
            rationale="Enables independent scaling and deployment",
            timestamp="2025-01-22T11:00:00",
            context={'constraint': 'Must support 10k RPS', 'pattern': 'Event-driven communication'}
        ),
        Decision(
            id="dec-2",
            category="security",
            description="Implement OAuth2 + JWT",
            rationale="Industry standard with good library support",
            timestamp="2025-01-22T12:00:00",
            context={}
        ),
    ]

    consultations = [
        Consultation(
            id="c1",
            timestamp="2025-01-22T10:00:00",
            query="API rate limiting strategy?",
            mode="multi-persona",
            personas_consulted=["platform-builder", "security-guardian"],
            context="api-design",
            synthesis="Use token bucket with Redis",
            decision_id="dec-1"
        ),
        Consultation(
            id="c2",
            timestamp="2025-01-22T11:30:00",
            query="Error handling best practices?",
            mode="quick",
            personas_consulted=["pragmatic-architect"],
            context="code-quality",
            synthesis="Use structured errors"
        ),
    ]

    return SessionState(
        session_id="test-session",
        started_at="2025-01-22T09:00:00",
        last_updated="2025-01-22T14:00:00",
        decisions=decisions,
        consultations=consultations,
        active_constraints=["Must support 10k RPS", "99.9% uptime SLA"],
        patterns_agreed=["Event-driven communication", "Infrastructure as Code"]
    )


class TestConsultationExporter:
    """Test ConsultationExporter functionality."""

    def test_export_markdown_with_metadata(self, sample_consultation):
        """Test markdown export with metadata."""
        output = ConsultationExporter.export_consultation(
            sample_consultation,
            format="markdown",
            include_metadata=True
        )

        assert "# Consultation Report" in output
        assert "test-123" in output
        assert "2025-01-22T10:00:00" in output
        assert "multi-persona" in output
        assert "api-design" in output
        assert "How should we implement API rate limiting?" in output
        assert "Platform Builder" in output
        assert "Security Guardian" in output
        assert "Pragmatic Architect" in output
        assert "token bucket algorithm" in output
        assert "dec-456" in output
        assert "Generated by Sensei MCP v0.4.0" in output

    def test_export_markdown_without_metadata(self, sample_consultation):
        """Test markdown export without metadata."""
        output = ConsultationExporter.export_consultation(
            sample_consultation,
            format="markdown",
            include_metadata=False
        )

        assert "# Consultation Report" in output
        assert "test-123" not in output  # ID excluded
        assert "How should we implement API rate limiting?" in output
        assert "token bucket algorithm" in output

    def test_export_markdown_no_decision(self, sample_consultation_no_decision):
        """Test markdown export for consultation without decision."""
        output = ConsultationExporter.export_consultation(
            sample_consultation_no_decision,
            format="markdown"
        )

        assert "Linked Decision" not in output

    def test_export_json(self, sample_consultation):
        """Test JSON export."""
        output = ConsultationExporter.export_consultation(
            sample_consultation,
            format="json"
        )

        data = json.loads(output)
        assert data["id"] == "test-123"
        assert data["query"] == "How should we implement API rate limiting?"
        assert data["mode"] == "multi-persona"
        assert len(data["personas_consulted"]) == 3
        assert "platform-builder" in data["personas_consulted"]
        assert data["context"] == "api-design"
        assert "token bucket" in data["synthesis"]
        assert data["decision_id"] == "dec-456"

    def test_export_text_with_metadata(self, sample_consultation):
        """Test text export with metadata."""
        output = ConsultationExporter.export_consultation(
            sample_consultation,
            format="text",
            include_metadata=True
        )

        assert "CONSULTATION REPORT" in output
        assert "ID: test-123" in output
        assert "Date: 2025-01-22T10:00:00" in output
        assert "Mode: multi-persona" in output
        assert "Context: api-design" in output
        assert "QUERY:" in output
        assert "PERSONAS CONSULTED:" in output
        assert "SYNTHESIS:" in output
        assert "Linked Decision: dec-456" in output

    def test_export_text_without_metadata(self, sample_consultation):
        """Test text export without metadata."""
        output = ConsultationExporter.export_consultation(
            sample_consultation,
            format="text",
            include_metadata=False
        )

        assert "CONSULTATION REPORT" in output
        assert "ID:" not in output
        assert "Date:" not in output
        assert "QUERY:" in output
        assert "SYNTHESIS:" in output

    def test_export_default_format(self, sample_consultation):
        """Test that markdown is default format."""
        output = ConsultationExporter.export_consultation(sample_consultation)
        assert "# Consultation Report" in output


class TestSessionExporter:
    """Test SessionExporter functionality."""

    def test_export_markdown_all_sections(self, sample_session):
        """Test markdown export with all sections."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="markdown",
            include=["decisions", "consultations", "constraints", "patterns"]
        )

        # Check header
        assert "# Session Summary: test-session" in output
        assert "2025-01-22T09:00:00" in output
        assert "2025-01-22T14:00:00" in output

        # Check ADRs section
        assert "## Architecture Decision Records (ADRs)" in output
        assert "Total decisions: 2" in output
        assert "### ADR 1: Use microservices architecture" in output
        assert "**Category:** architecture" in output
        assert "**Adds Constraint:** Must support 10k RPS" in output
        assert "**Establishes Pattern:** Event-driven communication" in output
        assert "### ADR 2: Implement OAuth2 + JWT" in output

        # Check consultation history
        assert "## Recent Consultation History" in output
        assert "API rate limiting strategy?" in output
        assert "Error handling best practices?" in output

        # Check constraints
        assert "## Active Constraints" in output
        assert "Must support 10k RPS" in output
        assert "99.9% uptime SLA" in output

        # Check patterns
        assert "## Agreed Patterns" in output
        assert "Event-driven communication" in output
        assert "Infrastructure as Code" in output

        # Check footer
        assert "## How to Use This Summary" in output
        assert "Generated by Sensei MCP v0.4.0" in output

    def test_export_markdown_decisions_only(self, sample_session):
        """Test markdown export with decisions only."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="markdown",
            include=["decisions"]
        )

        assert "## Architecture Decision Records (ADRs)" in output
        assert "## Recent Consultation History" not in output
        assert "## Active Constraints" not in output
        assert "## Agreed Patterns" not in output

    def test_export_markdown_max_consultations(self, sample_session):
        """Test consultation limiting."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="markdown",
            include=["consultations"],
            max_consultations=1
        )

        assert "Showing 1 most recent (total: 2)" in output

    def test_export_json_all_sections(self, sample_session):
        """Test JSON export with all sections."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="json",
            include=["decisions", "consultations", "constraints", "patterns"]
        )

        data = json.loads(output)
        assert data["session_id"] == "test-session"
        assert data["started_at"] == "2025-01-22T09:00:00"
        assert "generated_at" in data

        # Check decisions
        assert len(data["decisions"]) == 2
        assert data["decisions"][0]["id"] == "dec-1"
        assert data["decisions"][0]["category"] == "architecture"
        assert data["decisions"][0]["context"]["constraint"] == "Must support 10k RPS"
        assert data["decisions"][0]["context"]["pattern"] == "Event-driven communication"

        # Check consultations
        assert len(data["consultations"]) == 2
        assert data["consultations"][0]["id"] == "c1"
        assert data["consultations"][0]["mode"] == "multi-persona"

        # Check constraints and patterns
        assert len(data["active_constraints"]) == 2
        assert len(data["patterns_agreed"]) == 2

    def test_export_json_selective(self, sample_session):
        """Test JSON export with selective includes."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="json",
            include=["decisions", "constraints"]
        )

        data = json.loads(output)
        assert "decisions" in data
        assert "active_constraints" in data
        assert "consultations" not in data
        assert "patterns_agreed" not in data

    def test_export_text_format(self, sample_session):
        """Test text format export."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="text",
            include=["decisions", "consultations"]
        )

        assert "SESSION SUMMARY: test-session" in output
        assert "=" * 70 in output
        assert "DECISIONS:" in output
        assert "Use microservices architecture (architecture)" in output
        assert "RECENT CONSULTATIONS" in output
        assert "API rate limiting strategy?" in output

    def test_export_default_includes(self, sample_session):
        """Test that default includes all sections."""
        output = SessionExporter.export_session_summary(
            sample_session,
            format="markdown"
        )

        # Should include all by default
        assert "Architecture Decision Records" in output
        assert "Recent Consultation History" in output
        assert "Active Constraints" in output
        assert "Agreed Patterns" in output

    def test_export_empty_session(self):
        """Test exporting empty session."""
        empty_session = SessionState(
            session_id="empty",
            started_at="2025-01-22T10:00:00",
            last_updated="2025-01-22T11:00:00",
            decisions=[],
            consultations=[],
            active_constraints=[],
            patterns_agreed=[]
        )

        output = SessionExporter.export_session_summary(empty_session, format="markdown")

        assert "# Session Summary: empty" in output
        # Sections should not appear if empty
        assert "Total decisions: 0" not in output

    def test_decision_without_context(self):
        """Test exporting decision without constraint/pattern in context."""
        session = SessionState(
            session_id="test",
            started_at="2025-01-22T10:00:00",
            last_updated="2025-01-22T11:00:00",
            decisions=[
                Decision(
                    id="d1",
                    category="standard",
                    description="Use TypeScript",
                    rationale="Type safety",
                    timestamp="2025-01-22T10:30:00",
                    context={}  # Empty context
                )
            ],
            consultations=[],
            active_constraints=[],
            patterns_agreed=[]
        )

        output = SessionExporter.export_session_summary(session, format="markdown")

        assert "Use TypeScript" in output
        assert "Type safety" in output
        # Should not have constraint/pattern sections
        assert "**Adds Constraint:**" not in output
        assert "**Establishes Pattern:**" not in output

    def test_consultation_truncation(self, sample_session):
        """Test that long consultation synthesis gets truncated in markdown."""
        # Add consultation with long synthesis
        long_synthesis = "A" * 500  # 500 chars
        sample_session.consultations.append(
            Consultation(
                id="c3",
                timestamp="2025-01-22T12:00:00",
                query="Long answer test?",
                mode="quick",
                personas_consulted=["pragmatic-architect"],
                context="general",
                synthesis=long_synthesis
            )
        )

        output = SessionExporter.export_session_summary(
            sample_session,
            format="markdown",
            include=["consultations"]
        )

        # Check truncation happened
        assert "..." in output
        # Full synthesis should not be in output
        assert long_synthesis not in output
