"""Tests for the X Content Pipeline — output gate, tweet queue, approval stages."""

import sys
import os
import sqlite3
import json

# Add telegram/ to path for imports
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "telegram"))


# ─── Output Gate Tests ───────────────────────────────────────────────

from output_gate import classify, gate_for_tweet_queue, GateResult


def test_system_content_blocked():
    """Pipeline messages are classified as system."""
    system_messages = [
        "PR #2274 merged to main via cherry-pick",
        "Pipeline extracted 5 claims from batch-extract-50.sh run",
        "Schema v14 migration applied, approval_queue table created",
        "Qdrant has 1004 vectors, embed-on-merge running",
        "VPS deploy: scp merge.py to /opt/teleo-eval/pipeline/",
        "Ganymede reviewed and approved the code changes",
        "PIPELINE_OWNED_PREFIXES filter working correctly",
    ]
    for msg in system_messages:
        result = classify(msg)
        assert not result.is_public, f"System message passed gate: {msg!r}"
        assert len(result.blocked_reasons) > 0


def test_public_content_passes():
    """Legitimate public content passes the gate."""
    public_messages = [
        "Futarchy governance is the most underrated coordination mechanism in crypto right now. Here's why the market is wrong about MetaDAO.",
        "The GLP-1 revolution isn't just about weight loss. New kidney data from FLOW trial shows 24% reduction in disease progression.",
        "Thread: Why I think AI alignment needs more empirical evidence and less theoretical speculation",
        "Interesting take from Shapiro on how AI will transform creative industries. The talent embrace angle is underappreciated.",
    ]
    for msg in public_messages:
        result = classify(msg)
        assert result.is_public, f"Public message blocked: {msg!r} — reasons: {result.blocked_reasons}"


def test_mixed_content_blocked():
    """Content with system signals defaults to blocking (safety)."""
    mixed = "Great PR #2274 about futarchy mechanisms merged today"
    result = classify(mixed)
    assert not result.is_public, "Mixed system+public content should be blocked"


def test_empty_content_blocked():
    """Empty content is blocked."""
    assert not classify("")
    assert not classify("   ")
    assert not classify(None)


def test_internal_urls_blocked():
    """Internal URLs are blocked by tweet gate."""
    result = gate_for_tweet_queue("Check out http://localhost:3000/teleo/repo")
    assert not result.is_public
    assert any("internal URL" in r for r in result.blocked_reasons)


def test_short_content_blocked():
    """Very short content is blocked by tweet gate."""
    result = gate_for_tweet_queue("ok")
    assert not result.is_public
    assert any("too short" in r for r in result.blocked_reasons)


def test_gate_result_bool():
    """GateResult is truthy when public, falsy when blocked."""
    assert GateResult(True, [], 0.9)
    assert not GateResult(False, ["test"], 0.9)


# ─── Tweet Submission Tests ──────────────────────────────────────────

def _make_db():
    """Create an in-memory DB with approval_queue table."""
    conn = sqlite3.connect(":memory:")
    conn.row_factory = sqlite3.Row
    conn.execute("""CREATE TABLE approval_queue (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        type TEXT NOT NULL,
        content TEXT NOT NULL,
        originating_agent TEXT NOT NULL,
        context TEXT,
        leo_review_status TEXT DEFAULT 'pending_leo',
        leo_review_note TEXT,
        status TEXT DEFAULT 'pending',
        decision_by TEXT,
        rejection_reason TEXT,
        telegram_message_id INTEGER,
        submitted_at TEXT DEFAULT (datetime('now')),
        decided_at TEXT,
        expires_at TEXT
    )""")
    return conn


def test_submit_tweet_draft():
    """Valid tweet draft enters the approval queue."""
    try:
        from x_publisher import submit_tweet_draft
    except ImportError:
        print("    (skipped — aiohttp not installed)")
        return
    conn = _make_db()

    request_id, error = submit_tweet_draft(
        conn,
        content="Futarchy governance is the most underrated mechanism in crypto. The market is systematically mispricing coordination infrastructure.",
        agent="hermes",
        post_type="original",
    )

    assert error is None, f"Submit failed: {error}"
    assert request_id > 0

    row = conn.execute("SELECT * FROM approval_queue WHERE id = ?", (request_id,)).fetchone()
    assert row["type"] == "tweet"
    assert row["originating_agent"] == "hermes"
    assert row["leo_review_status"] == "pending_leo"
    ctx = json.loads(row["context"])
    assert ctx["post_type"] == "original"
    assert ctx["target_account"] == "TeleoHumanity"


def test_submit_blocks_system_content():
    """System content is rejected before entering the queue."""
    try:
        from x_publisher import submit_tweet_draft
    except ImportError:
        print("    (skipped — aiohttp not installed)")
        return
    conn = _make_db()

    request_id, error = submit_tweet_draft(
        conn,
        content="PR #2274 merged via cherry-pick. Pipeline schema v14 deployed to VPS.",
        agent="hermes",
    )

    assert request_id == -1
    assert "Output gate blocked" in error
    # Verify nothing was inserted
    count = conn.execute("SELECT COUNT(*) FROM approval_queue").fetchone()[0]
    assert count == 0


def test_submit_blocks_opsec():
    """OPSEC-violating content is rejected."""
    try:
        from x_publisher import submit_tweet_draft
    except ImportError:
        print("    (skipped — aiohttp not installed)")
        return
    conn = _make_db()

    request_id, error = submit_tweet_draft(
        conn,
        content="Excited to announce our $5M Series A raise! The deal terms are amazing.",
        agent="hermes",
    )

    assert request_id == -1
    assert "OPSEC" in error


def test_submit_reply_tweet():
    """Reply tweets include reply_to_url in context."""
    try:
        from x_publisher import submit_tweet_draft
    except ImportError:
        print("    (skipped — aiohttp not installed)")
        return
    conn = _make_db()

    request_id, error = submit_tweet_draft(
        conn,
        content="Great point about futarchy adoption friction. The real bottleneck is UX, not mechanism design.",
        agent="rio",
        post_type="reply",
        reply_to_url="https://x.com/user/status/12345",
    )

    assert error is None
    ctx = json.loads(conn.execute(
        "SELECT context FROM approval_queue WHERE id = ?", (request_id,)
    ).fetchone()["context"])
    assert ctx["reply_to_url"] == "https://x.com/user/status/12345"
    assert ctx["post_type"] == "reply"


# ─── Approval Stages Tests ──────────────────────────────────────────

from approval_stages import (
    OutputGateStage, OpsecStage, Vote, StageResult,
    run_sync_stages, register_stage, ApprovalStage,
)


def test_output_gate_stage_passes_public():
    """Output gate stage approves public content."""
    stage = OutputGateStage()
    result = stage.check({
        "content": "AI alignment needs empirical evidence, not just theory. Here's what the data shows.",
        "originating_agent": "theseus",
    })
    assert result.vote == Vote.APPROVE


def test_output_gate_stage_blocks_system():
    """Output gate stage rejects system content."""
    stage = OutputGateStage()
    result = stage.check({
        "content": "Pipeline merge.py deployed to VPS via scp, systemd restarted",
        "originating_agent": "epimetheus",
    })
    assert result.vote == Vote.REJECT


def test_opsec_stage_blocks_financials():
    """OPSEC stage rejects financial content."""
    try:
        stage = OpsecStage()
        result = stage.check({
            "content": "Our $10M fund is performing well with 23.5% returns",
        })
        assert result.vote == Vote.REJECT
    except ImportError:
        # approvals.py needs telegram module — test OPSEC patterns directly
        import re
        pattern = re.compile(r"\$[\d,.]+[KMBkmb]?\b", re.IGNORECASE)
        assert pattern.search("Our $10M fund")


def test_opsec_stage_passes_clean():
    """OPSEC stage passes clean content."""
    try:
        stage = OpsecStage()
        result = stage.check({
            "content": "Futarchy governance shows promise for decentralized coordination",
        })
        assert result.vote == Vote.APPROVE
    except ImportError:
        # approvals.py needs telegram — just verify no OPSEC patterns match
        import re
        patterns = [
            re.compile(r"\$[\d,.]+[KMBkmb]?\b", re.IGNORECASE),
            re.compile(r"\b(deal terms?|valuation|cap table)\b", re.IGNORECASE),
        ]
        content = "Futarchy governance shows promise for decentralized coordination"
        assert not any(p.search(content) for p in patterns)


def test_sync_stages_block_system():
    """Full pipeline blocks system content at output gate (stage 0)."""
    result = run_sync_stages({
        "content": "PR #2274 cherry-pick merged via pipeline, schema v14 deployed",
        "originating_agent": "epimetheus",
        "type": "tweet",
    })
    assert not result.approved
    assert any(sr.stage_name == "output_gate" and sr.vote == Vote.REJECT
               for sr in result.stage_results)


def test_sync_stages_pass_public():
    """Full pipeline passes public content through to human stage (abstain)."""
    result = run_sync_stages({
        "content": "The convergence of futarchy governance and AI alignment is the most important intersection nobody is talking about.",
        "originating_agent": "hermes",
        "type": "tweet",
    })
    # Not "approved" yet because human stage abstains (async)
    # But no rejections
    rejects = [sr for sr in result.stage_results if sr.vote == Vote.REJECT]
    assert len(rejects) == 0


def test_custom_stage_registration():
    """Custom stages can be registered and run."""

    class TestStage(ApprovalStage):
        name = "test_custom"
        priority = 5  # between opsec (1) and human (10)
        weight = 0.5

        def check(self, request):
            if "test_block" in request.get("content", ""):
                return StageResult(self.name, Vote.REJECT, self.weight, "Test blocked")
            return StageResult(self.name, Vote.APPROVE, self.weight, "Test passed")

    register_stage(TestStage())

    # Verify it runs in the pipeline
    result = run_sync_stages({
        "content": "test_block this content",
        "originating_agent": "test",
        "type": "tweet",
    })
    assert any(sr.stage_name == "test_custom" for sr in result.stage_results)


# ─── Run all tests ───────────────────────────────────────────────────

if __name__ == "__main__":
    tests = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
    passed = 0
    failed = 0
    for test in tests:
        try:
            test()
            print(f"  PASS  {test.__name__}")
            passed += 1
        except Exception as e:
            print(f"  FAIL  {test.__name__}: {e}")
            failed += 1
    print(f"\n{passed} passed, {failed} failed out of {passed + failed}")
    sys.exit(1 if failed else 0)
