"""Deterministic docs refresh-llm tests with router-aware summary."""

from __future__ import annotations

import json
from typing import TYPE_CHECKING

from typer.testing import CliRunner

from dopetask.cli import cli
from dopetask.docs.refresh_llm import AUTOGEN_END, AUTOGEN_START, run_refresh_llm

if TYPE_CHECKING:
    from pathlib import Path


RUNNER = CliRunner()


def _write_target_files(repo_root: Path, *, include_codex_markers: bool = True) -> None:
    (repo_root / ".dopetaskroot").write_text("", encoding="utf-8")
    (repo_root / ".dopetask").mkdir(parents=True, exist_ok=True)
    (repo_root / ".dopetask" / "project.json").write_text(
        json.dumps({"project_id": "dopetask.core"}, sort_keys=True, indent=2) + "\n",
        encoding="utf-8",
    )

    (repo_root / "AGENTS.md").write_text(
        f"# AGENTS\n\n{AUTOGEN_START}\nold\n{AUTOGEN_END}\n",
        encoding="utf-8",
    )
    (repo_root / "CLAUDE.md").write_text(
        f"# CLAUDE\n\n{AUTOGEN_START}\nold\n{AUTOGEN_END}\n",
        encoding="utf-8",
    )

    if include_codex_markers:
        codex_text = f"# CODEX\n\n{AUTOGEN_START}\nold\n{AUTOGEN_END}\n"
    else:
        codex_text = "# CODEX\n\nStatic header.\n"
    (repo_root / "CODEX.md").write_text(codex_text, encoding="utf-8")


def test_determinism_same_inputs_same_block_and_hash(tmp_path: Path) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)
    _write_target_files(repo_root)

    first = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)
    second = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)

    assert first["autogen_block"] == second["autogen_block"]
    assert first["command_surface_hash"] == second["command_surface_hash"]


def test_idempotency_second_run_has_no_modifications(tmp_path: Path) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)
    _write_target_files(repo_root)

    run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)
    second = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)

    assert second["modified"] == []
    assert second["created"] == []


def test_refusal_on_malformed_marker_structure_exit_2(tmp_path: Path, monkeypatch) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)

    (repo_root / ".dopetaskroot").write_text("dopetask", encoding="utf-8")
    dopetask_dir = repo_root / ".dopetask"
    dopetask_dir.mkdir(parents=True, exist_ok=True)
    dopetask_dir.joinpath("project.json").write_text(
        json.dumps(
            {
                "project_id": "dopetask.core",
                "project_slug": "dopeTask",
                "repo_remote_hint": "dopeTask",
            }
        ),
        encoding="utf-8",
    )

    (repo_root / "AGENTS.md").write_text(f"# AGENTS\n{AUTOGEN_START}\n", encoding="utf-8")
    (repo_root / "CLAUDE.md").write_text(f"# CLAUDE\n{AUTOGEN_START}\nold\n{AUTOGEN_END}\n", encoding="utf-8")
    (repo_root / "CODEX.md").write_text(f"# CODEX\n{AUTOGEN_START}\nold\n{AUTOGEN_END}\n", encoding="utf-8")

    monkeypatch.chdir(repo_root)
    result = RUNNER.invoke(cli, ["docs", "refresh-llm", "--repo-root", str(repo_root)])

    assert result.exit_code == 2
    assert "Invalid AUTOGEN marker structure" in result.stdout


def test_codex_marker_auto_insertion_when_missing(tmp_path: Path) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)
    _write_target_files(repo_root, include_codex_markers=False)

    first = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)
    codex = (repo_root / "CODEX.md").read_text(encoding="utf-8")

    assert "CODEX.md" in first["created"]
    assert codex.count(AUTOGEN_START) == 1
    assert codex.count(AUTOGEN_END) == 1

    second = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)
    codex_again = (repo_root / "CODEX.md").read_text(encoding="utf-8")

    assert second["created"] == []
    assert codex_again.count(AUTOGEN_START) == 1
    assert codex_again.count(AUTOGEN_END) == 1


def test_check_mode_returns_exit_1_on_drift(tmp_path: Path, monkeypatch) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)
    _write_target_files(repo_root)

    run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)

    agents = (repo_root / "AGENTS.md").read_text(encoding="utf-8")
    agents = agents.replace("Generated by: dopetask docs refresh-llm", "Generated by: drift", 1)
    (repo_root / "AGENTS.md").write_text(agents, encoding="utf-8")

    monkeypatch.chdir(repo_root)
    result = RUNNER.invoke(cli, ["docs", "refresh-llm", "--repo-root", str(repo_root), "--check"])

    assert result.exit_code == 1
    report = json.loads(
        (repo_root / "out" / "dopetask_docs_refresh_llm" / "DOCS_REFRESH_LLM_REPORT.json").read_text(
            encoding="utf-8"
        )
    )
    assert report["status"] == "drift"


def test_router_summary_source_selection_and_ladder_order(tmp_path: Path) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)
    _write_target_files(repo_root)

    no_repo_availability = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)
    assert no_repo_availability["availability_source"] == "default"
    assert "### Assisted Routing (dopetask route)" in no_repo_availability["autogen_block"]

    availability_path = repo_root / ".dopetask" / "runtime" / "availability.yaml"
    availability_path.parent.mkdir(parents=True, exist_ok=True)
    availability_path.write_text(
        """
models:
  zeta-model:
    strengths: [tests]
    cost_tier: medium
    context: medium
  alpha-model:
    strengths: [cheap]
    cost_tier: cheap
    context: small
runners:
  zrunner:
    available: true
    strengths: [code_edit]
  arunner:
    available: true
    strengths: [planning]
policy:
  max_cost_tier: medium
  min_total_score: 61
  stop_on_ambiguity: true
  escalation_ladder: [zeta-model, alpha-model]
""".lstrip(),
        encoding="utf-8",
    )

    with_repo_availability = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=False)
    block = with_repo_availability["autogen_block"]

    assert with_repo_availability["availability_source"] == "repo"
    assert "- Available runners: arunner, zrunner" in block
    assert "- Available models: alpha-model, zeta-model" in block
    assert "- escalation_ladder: [zeta-model, alpha-model]" in block


def test_command_tree_contains_nested_leaf_depth(tmp_path: Path) -> None:
    repo_root = tmp_path / "repo"
    repo_root.mkdir(parents=True, exist_ok=True)
    _write_target_files(repo_root)
    result = run_refresh_llm(repo_root=repo_root, cli_app=cli, check=True)
    block = result["autogen_block"]

    assert "### Command Tree" in block
    assert "- dopetask docs" in block
    assert "  - dopetask docs refresh-llm" in block
    assert "- dopetask project" in block
    assert "    - dopetask project shell init" in block
    assert "  - dopetask route plan" in block
