from __future__ import annotations

import pytest

from api.doi_engine import evaluate, evaluate_scope_health


VALID_SCOPE = """# SCOPE

## One-liner
One sentence.

## Core Idea
Core idea.

## In Scope
- One thing

## Out of Scope
- Another thing

## Relevant When
- Useful

## Not Relevant When
- Not useful

## Current State
Active.

## How It Fits
Fits here.

## Terminology
- Term

## Related / Overlapping
- None

## Provided Capabilities

```capability
type: api
title: Example API
```
"""


async def _create_domain(client, slug="scopedom"):
    r = await client.post("/domains/", json={"slug": slug, "name": "Scope Domain"})
    assert r.status_code == 201, r.text
    return r.json()


async def _create_repo(client, domain_slug, local_path, slug="scope-repo"):
    r = await client.post("/repos/", json={
        "slug": slug,
        "name": "Scope Repo",
        "domain_slug": domain_slug,
        "local_path": str(local_path),
        "remote_url": "https://example.invalid/scope-repo.git",
    })
    assert r.status_code == 201, r.text
    return r.json()


def test_scope_health_reports_section_and_capability_detail(tmp_path):
    (tmp_path / "SCOPE.md").write_text("# SCOPE\n", encoding="utf-8")

    issues = evaluate_scope_health({"slug": "stub", "local_path": str(tmp_path)})
    by_id = {issue["id"]: issue for issue in issues}

    assert by_id["C5a"]["status"] == "pass"
    assert by_id["C5b"]["status"] == "warn"
    assert "One-liner" in by_id["C5b"]["missing_sections"]
    assert "One-liner" in by_id["C5b"]["needs_refresh_sections"]
    assert by_id["C5c"]["status"] == "warn"
    assert by_id["C5c"]["needs_refresh_sections"] == ["Provided Capabilities"]


@pytest.mark.asyncio
async def test_doi_reports_c5a_c5b_c5c_separately(tmp_path):
    (tmp_path / "SCOPE.md").write_text(VALID_SCOPE, encoding="utf-8")

    report = await evaluate(
        {
            "slug": "valid",
            "domain_slug": "scopedom",
            "local_path": str(tmp_path),
            "remote_url": "https://example.invalid/valid.git",
        },
        skip_consistency=True,
        prefetch={
            "domain_status": {"scopedom": "active"},
            "tpsc_snap_counts": {"valid": 0},
            "active_goal_counts": {"valid": 0},
        },
    )

    c5 = {criterion.id: criterion for criterion in report.criteria if criterion.id.startswith("C5")}
    assert set(c5) == {"C5a", "C5b", "C5c"}
    assert c5["C5a"].status == "pass"
    assert c5["C5b"].status == "pass"
    assert c5["C5c"].status == "pass"


class TestRepoDispatchScopeHealth:
    async def test_dispatch_flags_stub_scope_for_review(self, client, tmp_path):
        await _create_domain(client)
        (tmp_path / "SCOPE.md").write_text("# SCOPE\n", encoding="utf-8")
        await _create_repo(client, "scopedom", tmp_path, slug="stub-scope")

        r = await client.get("/repos/stub-scope/dispatch")
        assert r.status_code == 200, r.text
        body = r.json()

        assert body["scope_needs_review"] is True
        by_id = {issue["id"]: issue for issue in body["scope_issue_details"]}
        assert by_id["C5b"]["missing_sections"]
        assert by_id["C5c"]["needs_refresh_sections"] == ["Provided Capabilities"]

    async def test_dispatch_reports_valid_scope_without_review(self, client, tmp_path):
        await _create_domain(client)
        (tmp_path / "SCOPE.md").write_text(VALID_SCOPE, encoding="utf-8")
        await _create_repo(client, "scopedom", tmp_path, slug="valid-scope")

        r = await client.get("/repos/valid-scope/dispatch")
        assert r.status_code == 200, r.text
        body = r.json()

        assert body["scope_needs_review"] is False
        assert {issue["id"]: issue["status"] for issue in body["scope_issue_details"]} == {
            "C5a": "pass",
            "C5b": "pass",
            "C5c": "pass",
        }

    async def test_scope_health_list_filters_reachable_repos_needing_review(self, client, tmp_path):
        await _create_domain(client)
        stub_path = tmp_path / "stub"
        valid_path = tmp_path / "valid"
        stub_path.mkdir()
        valid_path.mkdir()
        (stub_path / "SCOPE.md").write_text("# SCOPE\n", encoding="utf-8")
        (valid_path / "SCOPE.md").write_text(VALID_SCOPE, encoding="utf-8")
        await _create_repo(client, "scopedom", stub_path, slug="stub-list")
        await _create_repo(client, "scopedom", valid_path, slug="valid-list")

        r = await client.get("/repos/scope-health?needs_review=true&reachable_only=true")
        assert r.status_code == 200, r.text
        body = r.json()

        assert [entry["repo_slug"] for entry in body] == ["stub-list"]
        assert body[0]["path_available"] is True
        by_id = {issue["id"]: issue for issue in body[0]["scope_issue_details"]}
        assert by_id["C5b"]["needs_refresh_sections"]
