"""Integration test — SDK against production Railway backend.

Usage:
    NEXURE_API_KEY=nx_live_... python -m pytest tests/test_sdk_production.py -v

Or standalone:
    NEXURE_API_KEY=nx_live_... python tests/test_sdk_production.py
"""
from __future__ import annotations

import asyncio
import os
import sys

# Production Railway backend
PRODUCTION_URL = "https://nexure-api-production.up.railway.app/v1"


def get_client():
    from nexure import Nexure

    api_key = os.environ.get("NEXURE_API_KEY")
    if not api_key:
        print("ERROR: Set NEXURE_API_KEY environment variable")
        sys.exit(1)
    return Nexure(api_key=api_key, base_url=PRODUCTION_URL)


def test_list_decisions():
    """List decisions — should have seeded data."""
    nx = get_client()
    try:
        result = nx.decisions.list(limit=10)
        assert result.total > 0, f"Expected decisions, got total={result.total}"
        assert len(result.decisions) > 0
        d = result.decisions[0]
        assert d.id.startswith("dec_")
        assert d.decision_type in ("credit_underwriting", "claims_adjudication", "wealth_suitability")
        print(f"  Listed {len(result.decisions)} decisions (total: {result.total})")
    finally:
        nx.close()


def test_get_single_decision():
    """Get a known demo decision."""
    nx = get_client()
    try:
        # Use the clean approval scenario
        decision = nx.decisions.get("dec_ce21edac17d3")
        assert decision.id == "dec_ce21edac17d3"
        assert decision.decision_type == "credit_underwriting"
        assert decision.trust_score == 95
        print(f"  Got decision {decision.id}: {decision.action}, trust={decision.trust_score}")
    finally:
        nx.close()


def test_list_with_filters():
    """List with decision_type filter."""
    nx = get_client()
    try:
        result = nx.decisions.list(limit=5, decision_type="claims_adjudication")
        assert result.total > 0
        for d in result.decisions:
            assert d.decision_type == "claims_adjudication"
        print(f"  Filtered to claims: {result.total} total, got {len(result.decisions)}")
    finally:
        nx.close()


def test_record_decision():
    """Record a new decision via SDK."""
    nx = get_client()
    try:
        record = nx.decisions.record(
            decision_type="credit_underwriting",
            evidence={
                "fico_score": 720,
                "dti_ratio": 0.38,
                "loan_amount": 50000,
                "annual_income": 130000,
            },
            action="approve",
            decided_by="sdk_integration_test",
            trust_score=85,
            reasoning="SDK integration test — strong credit profile",
        )
        assert record.id.startswith("dec_")
        assert record.action == "approve"
        assert record.decided_by == "sdk_integration_test"
        assert record.trust_score == 85
        print(f"  Recorded decision {record.id} (seq #{record.sequence_number})")

        # Verify we can retrieve it
        fetched = nx.decisions.get(record.id)
        assert fetched.id == record.id
        assert fetched.evidence_snapshot["fico_score"] == 720
        print(f"  Verified retrieval of {fetched.id}")
    finally:
        nx.close()


def test_generate_brief():
    """Generate a brief (degraded — no LLM key on Railway)."""
    nx = get_client()
    try:
        brief = nx.briefs.generate(
            decision_type="credit_underwriting",
            evidence={
                "fico_score": 580,
                "dti_ratio": 0.52,
                "loan_amount": 75000,
                "annual_income": 45000,
                "loan_purpose": "debt_consolidation",
                "employment_status": "employed",
            },
        )
        assert brief.id.startswith("brf_")
        assert len(brief.flags) > 0, "Should trigger risk flags for poor credit"
        print(f"  Generated brief {brief.id}: {len(brief.flags)} flags, quality={brief.quality_score}")
    finally:
        nx.close()


def test_analytics_overview():
    """Analytics overview — should reflect 4000+ seeded decisions."""
    nx = get_client()
    try:
        overview = nx.analytics.overview(days=365)
        assert overview.total_decisions > 3000
        assert len(overview.action_breakdown) > 0
        print(
            f"  Overview: {overview.total_decisions} decisions, "
            f"override_rate={overview.override_rate:.1%}, "
            f"avg_trust={overview.avg_trust_score:.1f}"
        )
    finally:
        nx.close()


def test_analytics_overrides():
    """Override rates — should detect M. Johnson anomaly."""
    nx = get_client()
    try:
        overrides = nx.analytics.override_rates(lookback_days=365)
        assert overrides.team_override_rate > 0
        reviewers = {r.reviewer: r for r in overrides.reviewers}
        # M. Johnson should be flagged as anomaly
        assert "M. Johnson" in reviewers or "reviewer_mjohnson" in reviewers
        mjohnson_key = "M. Johnson" if "M. Johnson" in reviewers else "reviewer_mjohnson"
        mj = reviewers[mjohnson_key]
        assert mj.override_rate > 0.30, f"M. Johnson override rate should be >30%, got {mj.override_rate:.1%}"
        print(
            f"  Team override rate: {overrides.team_override_rate:.1%}, "
            f"M. Johnson: {mj.override_rate:.1%} (anomaly={mj.is_anomaly})"
        )
    finally:
        nx.close()


def test_analytics_drift():
    """Drift detection."""
    nx = get_client()
    try:
        drift = nx.analytics.drift(weeks=12)
        assert len(drift.weeks) > 0
        print(f"  Drift: {len(drift.weeks)} weeks analyzed, {len(drift.alerts)} alerts")
    finally:
        nx.close()


def test_ledger_verify():
    """Verify the hash chain integrity."""
    nx = get_client()
    try:
        result = nx.ledger.verify()
        assert result.valid, f"Ledger should be valid, got error: {result.error}"
        assert result.records_checked > 3000
        print(f"  Ledger valid: {result.records_checked} records verified")
    finally:
        nx.close()


def test_templates_list():
    """List available templates."""
    nx = get_client()
    try:
        result = nx.templates.list()
        assert len(result.templates) > 0
        names = [t.display_name for t in result.templates]
        print(f"  Templates: {', '.join(names)}")
    finally:
        nx.close()


def test_visibility_score():
    """Visibility score — composite 0-100 metric."""
    nx = get_client()
    try:
        score = nx.analytics.visibility_score()
        assert 0 <= score.score <= 100
        print(f"  Visibility Score: {score.score:.0f}/100 ({len(score.components)} components)")
    finally:
        nx.close()


def test_forensics():
    """Full forensic reconstruction."""
    nx = get_client()
    try:
        report = nx.decisions.forensics("dec_ce21edac17d3")
        assert report.record.id == "dec_ce21edac17d3"
        assert report.chain_verified
        assert report.package is not None
        print(
            f"  Forensics: chain_pos={report.chain_position}, "
            f"chain_len={report.chain_length}, verified={report.chain_verified}"
        )
    finally:
        nx.close()


def test_async_client():
    """Async client — list + get."""
    from nexure import AsyncNexure

    api_key = os.environ.get("NEXURE_API_KEY")

    async def _run():
        async with AsyncNexure(api_key=api_key, base_url=PRODUCTION_URL) as nx:
            # List
            result = await nx.decisions.list(limit=5)
            assert len(result.decisions) > 0
            print(f"  Async list: {len(result.decisions)} decisions")

            # Get
            d = await nx.decisions.get(result.decisions[0].id)
            assert d.id == result.decisions[0].id
            print(f"  Async get: {d.id}")

            # Analytics
            overview = await nx.analytics.overview(days=365)
            assert overview.total_decisions > 0
            print(f"  Async analytics: {overview.total_decisions} decisions")

    asyncio.run(_run())


# ── Standalone runner ──────────────────────────────────────────


def main():
    """Run all tests and report results."""
    tests = [
        ("List decisions", test_list_decisions),
        ("Get single decision", test_get_single_decision),
        ("List with filters", test_list_with_filters),
        ("Record new decision", test_record_decision),
        ("Generate brief", test_generate_brief),
        ("Analytics overview", test_analytics_overview),
        ("Analytics overrides", test_analytics_overrides),
        ("Analytics drift", test_analytics_drift),
        ("Ledger verify", test_ledger_verify),
        ("Templates list", test_templates_list),
        ("Visibility score", test_visibility_score),
        ("Forensics", test_forensics),
        ("Async client", test_async_client),
    ]

    passed = 0
    failed = 0

    print(f"\nNexure SDK Integration Tests")
    print(f"Backend: {PRODUCTION_URL}")
    print(f"{'=' * 60}\n")

    for name, fn in tests:
        try:
            print(f"[TEST] {name}")
            fn()
            print(f"  PASS\n")
            passed += 1
        except Exception as e:
            print(f"  FAIL: {e}\n")
            failed += 1

    print(f"{'=' * 60}")
    print(f"Results: {passed} passed, {failed} failed, {passed + failed} total")

    if failed:
        print("\nSome tests failed!")
        sys.exit(1)
    else:
        print("\nAll SDK integration tests passed!")


if __name__ == "__main__":
    main()
