import os
import subprocess
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Literal

import pytest

pytestmark = pytest.mark.skipif(
 not os.environ.get("TIER2_SANDBOX_TESTS"),
 reason="opt-in: report writer test off by default; set TIER2_SANDBOX_TESTS=1",
)

from scripts.tier2.write_report import (
 compute_report_path,
 compute_stopped_flag_path,
 TaskResult,
 write_failure_report,
)
from scripts.tier2.failcount import FailcountState


def test_report_path_under_tier2_failures_dir(monkeypatch, tmp_path) -> None:
 monkeypatch.setenv("TIER2_FAILURES_DIR", str(tmp_path / "failures"))
 path = compute_report_path("my_track", datetime(2026, 6, 16, 12, 0, 0, tzinfo=timezone.utc))
 assert path.parent == tmp_path / "failures"
 assert path.name.startswith("my_track_")
 assert path.name.endswith(".md")


def test_stopped_flag_path_under_tier2_failures_dir(monkeypatch, tmp_path) -> None:
 monkeypatch.setenv("TIER2_FAILURES_DIR", str(tmp_path / "failures"))
 path = compute_stopped_flag_path("my_track")
 assert path.parent == tmp_path / "failures"
 assert path.name == "my_track.STOPPED"


def test_report_has_7_sections(monkeypatch, tmp_path) -> None:
 monkeypatch.setenv("TIER2_FAILURES_DIR", str(tmp_path / "failures"))
 now = datetime(2026, 6, 16, 12, 0, 0, tzinfo=timezone.utc)
 started = datetime(2026, 6, 16, 11, 30, 0, tzinfo=timezone.utc)
 path = write_failure_report(
  track_name="my_track",
  branch_name="tier2/my_track",
  started_at=started,
  stopped_at=now,
  give_up_signal="red_phase_failures >= 3",
  completed_tasks=[
   TaskResult(task_id="1.1", phase="Commit", commit_sha="abc1234", summary="did thing 1"),
  ],
  current_task=TaskResult(
   task_id="1.2", phase="Red", commit_sha="", summary="writing test",
   error="AssertionError: expected 5, got 3",
  ),
  last_failures=["AssertionError on test_foo", "ImportError on test_bar"],
  state=FailcountState(red_phase_failures=3, green_phase_failures=0, no_progress_started_at=started),
  repo_path=Path("."),
 )
 content = path.read_text(encoding="utf-8")
 assert "## 1. Header" in content
 assert "## 2. Tasks Completed" in content
 assert "## 3. Current Task" in content
 assert "## 4. Last 3 Failures" in content
 assert "## 5. Failcount State" in content
 assert "## 6. Git State" in content
 assert "## 7. Recommendation" in content


def test_stopped_flag_created(monkeypatch, tmp_path) -> None:
 monkeypatch.setenv("TIER2_FAILURES_DIR", str(tmp_path / "failures"))
 now = datetime(2026, 6, 16, 12, 0, 0, tzinfo=timezone.utc)
 started = datetime(2026, 6, 16, 11, 30, 0, tzinfo=timezone.utc)
 write_failure_report(
  track_name="my_track",
  branch_name="tier2/my_track",
  started_at=started,
  stopped_at=now,
  give_up_signal="green_phase_failures >= 3",
  completed_tasks=[],
  current_task=TaskResult(task_id="1.1", phase="Green", commit_sha="", summary="", error=""),
  last_failures=[],
  state=FailcountState(),
  repo_path=Path("."),
 )
 flag = compute_stopped_flag_path("my_track")
 assert flag.exists()


def test_recommend_green_phase_stuck() -> None:
 from scripts.tier2.write_report import _recommend
 state = FailcountState(red_phase_failures=0, green_phase_failures=3)
 rec = _recommend(state, None)
 assert "green-phase" in rec.lower()


def test_truncate_long_text() -> None:
 from scripts.tier2.write_report import _truncate
 long_text = "\n".join(f"line {i}" for i in range(100))
 truncated = _truncate(long_text, max_lines=10)
 assert "line 0" in truncated
 assert "line 9" in truncated
 assert "truncated" in truncated
 assert "90 more lines" in truncated


def test_truncate_short_text_unchanged() -> None:
 from scripts.tier2.write_report import _truncate
 text = "short\ntext"
 assert _truncate(text) == text


def test_git_log_fallback_on_subprocess_error(monkeypatch, tmp_path) -> None:
 from scripts.tier2.write_report import _git_log_for_branch
 import scripts.tier2.write_report as wr
 def fake_run(*args, **kwargs):
  raise FileNotFoundError("no git")
 monkeypatch.setattr(wr.subprocess, "run", fake_run)
 result = _git_log_for_branch("any", tmp_path)
 assert "not available" in result.lower()
