"""Tests for register_from_classification CLI (STATE-WP-0065 P3)."""
from __future__ import annotations

import json
import subprocess
import sys
from pathlib import Path

import pytest

from api.classification import ClassificationData

REPO_ROOT = Path(__file__).resolve().parent.parent
SCRIPT = REPO_ROOT / "scripts" / "register_from_classification.py"


def test_cli_help():
    result = subprocess.run(
        [sys.executable, str(SCRIPT), "--help"],
        capture_output=True,
        text=True,
        cwd=REPO_ROOT,
    )
    assert result.returncode == 0
    assert "--repo-path" in result.stdout
    assert "--bulk" in result.stdout
    assert "--dry-run" in result.stdout


@pytest.mark.asyncio
async def test_dry_run_repo_path_state_hub():
    sys.path.insert(0, str(REPO_ROOT))
    from scripts.register_from_classification import run_registration
    import argparse

    args = argparse.Namespace(
        repo_path=str(REPO_ROOT),
        slug=None,
        bulk=False,
        dry_run=True,
        api=False,
        db=False,
        api_base="http://127.0.0.1:8000",
        json=False,
    )
    report = await run_registration(args)
    counts = report.counts()
    assert counts["invalid"] == 0
    assert counts["registered"] + counts["updated"] + counts["skipped"] >= 1
    assert any(r.slug == "state-hub" for r in report.results)
    # Valid classification file is always parsed even when DB domains are absent.
    assert not any("repo_classification block" in r.detail for r in report.results)


def test_json_report_shape():
    result = subprocess.run(
        [
            sys.executable,
            str(SCRIPT),
            "--repo-path",
            str(REPO_ROOT),
            "--dry-run",
            "--json",
        ],
        capture_output=True,
        text=True,
        cwd=REPO_ROOT,
    )
    payload = json.loads(result.stdout)
    assert payload["summary"]["invalid"] == 0
    assert "summary" in payload
    assert "results" in payload
    assert set(payload["summary"]) == {"registered", "updated", "skipped", "invalid"}


def test_git_fingerprint_uses_one_root(monkeypatch, tmp_path):
    from scripts import register_from_classification as registration

    first = "a" * 40
    second = "b" * 40
    monkeypatch.setattr(
        registration,
        "_git_value",
        lambda _path, _args: f"{first}\n{second}",
    )

    assert registration._git_fingerprint(tmp_path) == first


@pytest.mark.asyncio
async def test_api_update_separates_classification_from_identity(monkeypatch, tmp_path):
    from scripts import register_from_classification as registration

    calls = []

    def fake_api_request(method, path, *, api_base, body=None):
        calls.append((method, path, body))
        if method == "GET":
            return 200, {"slug": "example"}
        return 200, {"slug": "example"}

    monkeypatch.setattr(registration, "_api_request", fake_api_request)
    monkeypatch.setattr(registration, "_git_root", lambda path: path)
    monkeypatch.setattr(registration, "_git_value", lambda _path, _args: "origin")
    monkeypatch.setattr(registration, "_git_fingerprint", lambda _path: "a" * 40)
    report = registration.RegistrationReport()
    data = ClassificationData(
        category="infrastructure",
        domain="infotech",
        capability_tags=["infrastructure.state"],
    )

    await registration._upsert_via_api(
        slug="example",
        repo_path=tmp_path,
        data=data,
        dry_run=False,
        api_base="http://state-hub.test",
        report=report,
    )

    patch = next(call for call in calls if call[:2] == ("PATCH", "/repos/example"))
    assert patch[2]["domain_slug"] == "infotech"
    assert "local_path" not in patch[2]
    assert "remote_url" not in patch[2]
    assert "git_fingerprint" not in patch[2]
    assert ("POST", "/repos/example/paths") in [call[:2] for call in calls]
