"""Tests for P0 self-learning data capture."""

from __future__ import annotations

import httpx
import pytest

from logos_adk.agent import Agent
from logos_adk.learning import SQLiteLearningStore
from logos_adk.providers.mock import MockProvider


async def _request(app, method: str, path: str, **kwargs):
    transport = httpx.ASGITransport(app=app)
    async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client:
        return await client.request(method, path, **kwargs)


@pytest.mark.asyncio
async def test_learning_capture_builds_dataset_from_runs_feedback_and_outcomes(tmp_path):
    from logos_adk.serve import create_app

    agent = Agent("bot", model=MockProvider(responses=["draft answer"]))
    learning_store = SQLiteLearningStore(str(tmp_path / "learning.db"))
    app = create_app(
        [agent],
        learning_store=learning_store,
        api_keys={
            "learn-key": {
                "name": "learner",
                "scopes": ["agent:run", "learning:write", "learning:read"],
                "workspaces": ["acme"],
            }
        },
        require_workspace=True,
    )

    run_response = await _request(
        app,
        "POST",
        "/run",
        json={"prompt": "draft a listing", "session_id": "lead-1"},
        headers={
            "Authorization": "Bearer learn-key",
            "X-Workspace-Id": "acme",
            "X-Trace-Id": "trace-run-1",
            "X-Prompt-Version": "prompt-v3",
        },
    )
    assert run_response.status_code == 200
    run_payload = run_response.json()
    assert run_payload["trace_id"] == "trace-run-1"
    assert run_payload["workspace_id"] == "acme"
    assert run_payload["prompt_version"] == "prompt-v3"
    assert run_payload["config_fingerprint"]

    feedback_response = await _request(
        app,
        "POST",
        "/feedback",
        json={
            "run_id": run_payload["run_id"],
            "kind": "edited_answer",
            "corrected_output": "approved answer",
            "correction_notes": "shorter, more factual",
            "expected_output": "approved answer",
            "failure_types": ["style_miss", "hallucination"],
            "metadata": {"reviewer": "ops"},
        },
        headers={
            "Authorization": "Bearer learn-key",
            "X-Workspace-Id": "acme",
        },
    )
    assert feedback_response.status_code == 200
    feedback_payload = feedback_response.json()
    assert feedback_payload["trace_id"] == "trace-run-1"
    assert feedback_payload["session_id"] == "acme:lead-1"
    assert feedback_payload["workspace_id"] == "acme"
    assert feedback_payload["corrected_output"] == "approved answer"
    assert set(feedback_payload["failure_types"]) == {"style_miss", "hallucination"}

    outcome_response = await _request(
        app,
        "POST",
        "/outcomes",
        json={
            "trace_id": "trace-run-1",
            "kind": "conversion",
            "value": True,
            "metadata": {"channel": "marketplace"},
        },
        headers={
            "Authorization": "Bearer learn-key",
            "X-Workspace-Id": "acme",
        },
    )
    assert outcome_response.status_code == 200
    outcome_payload = outcome_response.json()
    assert outcome_payload["trace_id"] == "trace-run-1"
    assert outcome_payload["prompt_version"] == "prompt-v3"

    dataset_response = await _request(
        app,
        "POST",
        "/learning/datasets/build",
        json={"limit": 10, "include_unreviewed": False},
        headers={
            "Authorization": "Bearer learn-key",
            "X-Workspace-Id": "acme",
        },
    )
    assert dataset_response.status_code == 200
    dataset_payload = dataset_response.json()
    assert dataset_payload["summary"]["count"] == 1
    assert dataset_payload["summary"]["with_feedback"] == 1
    assert dataset_payload["summary"]["with_outcomes"] == 1

    example = dataset_payload["items"][0]
    assert example["input_text"] == "draft a listing"
    assert example["output_text"] == "draft answer"
    assert example["trace_id"] == "trace-run-1"
    assert example["session_id"] == "acme:lead-1"
    assert example["workspace_id"] == "acme"
    assert example["prompt_version"] == "prompt-v3"
    assert set(example["failure_types"]) == {"style_miss", "hallucination"}
    assert example["corrected_output"] == "approved answer"
    assert example["feedback"][0]["correction_notes"] == "shorter, more factual"
    assert example["outcomes"][0]["kind"] == "conversion"
    assert example["outcomes"][0]["value"] is True


@pytest.mark.asyncio
async def test_feedback_validation_rejects_unknown_failure_type(tmp_path):
    from logos_adk.serve import create_app

    agent = Agent("bot", model=MockProvider(responses=["ok"]))
    learning_store = SQLiteLearningStore(str(tmp_path / "learning.db"))
    app = create_app(
        [agent],
        learning_store=learning_store,
        api_keys={
            "learn-key": {
                "name": "learner",
                "scopes": ["agent:run", "learning:write"],
                "workspaces": ["acme"],
            }
        },
        require_workspace=True,
    )

    run_response = await _request(
        app,
        "POST",
        "/run",
        json={"prompt": "hello"},
        headers={
            "Authorization": "Bearer learn-key",
            "X-Workspace-Id": "acme",
            "X-Trace-Id": "trace-run-2",
        },
    )
    assert run_response.status_code == 200
    run_id = run_response.json()["run_id"]

    feedback_response = await _request(
        app,
        "POST",
        "/feedback",
        json={
            "run_id": run_id,
            "kind": "thumbs_down",
            "failure_types": ["made_up_bucket"],
        },
        headers={
            "Authorization": "Bearer learn-key",
            "X-Workspace-Id": "acme",
        },
    )
    assert feedback_response.status_code == 422
    payload = feedback_response.json()
    assert payload["error"] in ("invalid_feedback", "validation")


@pytest.mark.asyncio
async def test_learning_endpoints_require_learning_scopes(tmp_path):
    from logos_adk.serve import create_app

    agent = Agent("bot", model=MockProvider(responses=["ok"]))
    learning_store = SQLiteLearningStore(str(tmp_path / "learning.db"))
    app = create_app(
        [agent],
        learning_store=learning_store,
        api_keys={
            "run-key": {
                "name": "runner",
                "scopes": ["agent:run"],
                "workspaces": ["acme"],
            }
        },
        require_workspace=True,
    )

    response = await _request(
        app,
        "POST",
        "/feedback",
        json={"trace_id": "trace-1", "kind": "thumbs_up"},
        headers={
            "Authorization": "Bearer run-key",
            "X-Workspace-Id": "acme",
        },
    )
    assert response.status_code == 403
