"""Integration tests for end-to-end drift detection."""

from __future__ import annotations

import json
import re
from pathlib import Path

from typer.testing import CliRunner

from agentmd.cli import app

runner = CliRunner()


def _make_project(tmp_path: Path) -> Path:
    (tmp_path / "src").mkdir()
    (tmp_path / "tests").mkdir()
    (tmp_path / "src" / "main.py").write_text("def add(a, b):\n    return a + b\n", encoding="utf-8")
    (tmp_path / "tests" / "test_main.py").write_text(
        "from src.main import add\n\ndef test_add():\n    assert add(1, 2) == 3\n",
        encoding="utf-8",
    )
    (tmp_path / "pyproject.toml").write_text(
        "[project]\nname='demo'\nversion='0.1.0'\n",
        encoding="utf-8",
    )
    return tmp_path


def test_drift_stale_context_exit_one_and_text_output(tmp_path: Path) -> None:
    project = _make_project(tmp_path)
    generated = runner.invoke(app, ["generate", "--agent", "claude", str(project)])
    assert generated.exit_code == 0

    (project / "CLAUDE.md").write_text(
        "# CLAUDE.md\n\n## Project Overview\nThis file is stale.\n",
        encoding="utf-8",
    )

    result = runner.invoke(app, ["drift", "--agent", "claude", str(project)])
    assert result.exit_code == 1
    assert "Context drift detected." in result.output
    assert "CLAUDE.md: stale" in result.output


def test_drift_fresh_context_exit_zero(tmp_path: Path) -> None:
    project = _make_project(tmp_path)
    generated = runner.invoke(app, ["generate", "--agent", "claude", str(project)])
    assert generated.exit_code == 0

    result = runner.invoke(app, ["drift", "--agent", "claude", str(project)])
    assert result.exit_code == 0
    assert "Context files are fresh." in result.output
    assert "CLAUDE.md: fresh" in result.output


def test_drift_missing_context_file_is_detected(tmp_path: Path) -> None:
    project = _make_project(tmp_path)
    result = runner.invoke(app, ["drift", "--json", "--agent", "claude", str(project)])
    assert result.exit_code == 1

    payload = json.loads(result.output)
    assert payload["has_drift"] is True
    assert payload["summary"]["files"] == 1
    assert payload["summary"]["files_with_drift"] == 1
    assert payload["files"][0]["status"] == "missing"
    assert payload["files"][0]["sections_added"]


def test_drift_json_schema_structure(tmp_path: Path) -> None:
    project = _make_project(tmp_path)
    result = runner.invoke(app, ["drift", "--json", "--agent", "claude", str(project)])
    assert result.exit_code == 1

    payload = json.loads(result.output)
    assert payload["schema"] == {"name": "agentmd.drift.report", "version": "1.0.0"}
    assert set(payload["summary"]) >= {
        "files",
        "files_with_drift",
        "sections_added",
        "sections_removed",
        "sections_changed",
        "sections_stale",
    }

    file_report = payload["files"][0]
    assert set(file_report) >= {
        "agent",
        "file",
        "status",
        "has_drift",
        "sections_added",
        "sections_removed",
        "sections_changed",
        "sections_fresh",
        "sections_stale",
        "stale_details",
        "summary",
        "diff",
    }


def test_drift_markdown_output_structure(tmp_path: Path) -> None:
    project = _make_project(tmp_path)
    result = runner.invoke(app, ["drift", "--format", "markdown", "--agent", "claude", str(project)])
    assert result.exit_code == 1

    assert "## 🔍 agentmd Context Drift Report" in result.output
    assert re.search(r"⚠️ \d+ sections drifted in CLAUDE\.md", result.output)
    assert "| Section | Status | Detail |" in result.output
    assert "<details>" in result.output
    assert "```diff" in result.output
    assert "Generated by [agentmd](https://github.com/mikiships/agentmd)" in result.output
