"""Tests for the actions TUI page."""

from __future__ import annotations

import sys
import time
from pathlib import Path
from unittest.mock import MagicMock

import pytest
from pygit2 import Repository, init_repository
from pyratatui import Rect

from pygittools.tui.git_colors import init_tui_color_theme
from pygittools.tui.keys import key
from pygittools.tui.pages.actions import ActionsPage, actions_page
from pygittools.tui.types import PageAction, PageContext


def _repo_with_actions(tmp_path: Path, actions_body: str) -> PageContext:
	repo_dir = tmp_path / "repo"
	repo_dir.mkdir()
	repo = init_repository(str(repo_dir), bare=False)
	(repo_dir / "pyproject.toml").write_text(
		f'[project]\nname = "demo"\nversion = "0"\n\n[tool.pgt]\nactions = {actions_body}\n',
		encoding="utf-8",
	)
	venv_bin = repo_dir / ".venv" / "bin"
	venv_bin.mkdir(parents=True)
	(venv_bin / "python").symlink_to(sys.executable)
	return PageContext(repo=repo, repo_path=Path(repo.path))


def test_actions_page_empty(tmp_path: Path) -> None:
	repo_dir = tmp_path / "repo"
	repo_dir.mkdir()
	repo = init_repository(str(repo_dir), bare=False)
	ctx = PageContext(repo=repo, repo_path=Path(repo.path))
	page = actions_page()
	page.on_enter(ctx)
	assert "No pyproject" in page.status_text() or "No [tool.pgt]" in page.status_text()
	page.draw(MagicMock(), Rect(0, 0, 80, 20))
	assert page.handle_key(key("Esc")).action == PageAction.POP


@pytest.mark.skipif(sys.platform == "win32", reason="symlink venv setup requires SeCreateSymbolicLinkPrivilege")
def test_actions_page_lists_and_run(tmp_path: Path) -> None:
	ctx = _repo_with_actions(tmp_path, '[{ name = "ok", script = "ok.py" }]')
	init_tui_color_theme(ctx.repo)
	workdir = Path(ctx.repo.workdir)
	(workdir / "ok.py").write_text("print('done')\n", encoding="utf-8")
	page = ActionsPage()
	page.on_enter(ctx)
	assert "Enter run" in page.status_text()
	page.draw(MagicMock(), Rect(0, 0, 80, 20))
	# select the action row (index 1; 0 is Run all)
	page.handle_key(key("Down"))
	page.handle_key(key("Enter"))
	deadline = time.monotonic() + 5.0
	while time.monotonic() < deadline:
		page.on_idle()
		with page._lock:
			if page._active is None and page._states.get("ok") is not None:
				from pygittools.tui.pages.actions import _RunState

				if page._states["ok"] is not _RunState.IDLE:
					break
		time.sleep(0.05)
	assert page._states["ok"].name == "SUCCESS"
	assert page._messages["ok"] == "done"
	page.draw(MagicMock(), Rect(0, 0, 80, 20))


@pytest.mark.skipif(sys.platform == "win32", reason="symlink venv setup requires SeCreateSymbolicLinkPrivilege")
def test_actions_page_run_all_stops_on_failure(tmp_path: Path) -> None:
	ctx = _repo_with_actions(
		tmp_path,
		"""[
  { name = "bad", script = "bad.py" },
  { name = "good", script = "good.py" },
]""",
	)
	init_tui_color_theme(ctx.repo)
	workdir = Path(ctx.repo.workdir)
	(workdir / "bad.py").write_text("import sys\nsys.exit(1)\n", encoding="utf-8")
	(workdir / "good.py").write_text("print('should-not-run')\n", encoding="utf-8")
	page = ActionsPage()
	page.on_enter(ctx)
	page.handle_key(key("a"))
	deadline = time.monotonic() + 5.0
	while time.monotonic() < deadline:
		page.on_idle()
		with page._lock:
			if page._active is None:
				break
		time.sleep(0.05)
	from pygittools.tui.pages.actions import _RunState

	assert page._states["bad"] is _RunState.FAILURE
	assert page._states["good"] is _RunState.IDLE
	assert "good" not in page._messages


@pytest.mark.skipif(sys.platform == "win32", reason="symlink venv setup requires SeCreateSymbolicLinkPrivilege")
def test_actions_page_opens_from_factory(tmp_path: Path) -> None:
	ctx = _repo_with_actions(tmp_path, "[]")
	page = actions_page()
	page.on_enter(ctx)
	assert page.title == "actions"
	assert isinstance(ctx.repo, Repository)