"""Tests for project label and commit log helpers."""

from __future__ import annotations

import json
from pathlib import Path
from unittest.mock import MagicMock, patch

import pygit2
import pytest
from pyratatui import Rect

from pygittools.tui.keys import key
from pygittools.tui.log_list import CommitLogList
from pygittools.tui.project_label import repo_project_label

SIG = pygit2.Signature("t", "t@example.com", 0)


def test_repo_project_label_falls_back_to_worktree(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    settings = tmp_path / "settings.json"
    settings.write_text(json.dumps({"PROJECTROOT": str(tmp_path / "projects")}), encoding="utf-8")
    monkeypatch.setenv("PYGITWEB_SETTINGS_CONFIG", str(settings))
    repo_dir = tmp_path / "standalone"
    repo_dir.mkdir()
    pygit2.init_repository(str(repo_dir), bare=False)
    assert repo_project_label(repo_dir) == str(repo_dir.resolve())


def test_repo_project_label_uses_worktree_for_git_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    settings = tmp_path / "settings.json"
    settings.write_text(json.dumps({"PROJECTROOT": str(tmp_path / "projects")}), encoding="utf-8")
    monkeypatch.setenv("PYGITWEB_SETTINGS_CONFIG", str(settings))
    repo_dir = tmp_path / "pygitweb"
    repo_dir.mkdir()
    repo = pygit2.init_repository(str(repo_dir), bare=False)
    assert repo_project_label(Path(repo.path)) == str(repo_dir.resolve())


def test_commit_log_list_loads_head_commit(tmp_path: Path) -> None:
    repo = pygit2.init_repository(str(tmp_path / "repo"), bare=False)
    tree = repo.index.write_tree()
    repo.create_commit("HEAD", SIG, SIG, "feat: first", tree, [])
    log = CommitLogList()
    log.refresh(repo)
    assert str(repo.head.target)[:7] in log.status_hint()


def test_commit_log_list_empty_repo(repo: pygit2.Repository) -> None:
    log = CommitLogList()
    log.refresh(repo)
    assert log.status_hint() == "No commits — arrows move"
    log.draw(MagicMock(), Rect(0, 0, 80, 5), highlight=True)


def test_commit_log_list_navigation(tmp_path: Path) -> None:
    repo = pygit2.init_repository(str(tmp_path / "repo"), bare=False)
    tree = repo.index.write_tree()
    repo.create_commit("HEAD", SIG, SIG, "one", tree, [])
    log = CommitLogList()
    log.refresh(repo)
    log.handle_nav_key(key("Down"), repo)
    log.handle_nav_key(key("Up"), repo)
    with patch.object(log, "refresh") as refresh:
        log.handle_nav_key(key("x"), repo)
    refresh.assert_not_called()


def test_load_entries_without_head(repo: pygit2.Repository) -> None:
    from pygit2 import init_repository

    from pygittools.tui.log_list import _load_entries

    empty = init_repository(str(Path(repo.workdir).parent / "bare"), bare=True)
    assert _load_entries(empty) == []


def test_repo_project_label_under_projectroot(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.delenv("PYGITWEB_PROJECTROOT", raising=False)
    root = tmp_path / "root"
    project = root / "demo"
    project.mkdir(parents=True)
    pygit2.init_repository(str(project), bare=False)
    settings = tmp_path / "settings.json"
    settings.write_text(json.dumps({"PROJECTROOT": str(root)}), encoding="utf-8")
    monkeypatch.setenv("PYGITWEB_SETTINGS_CONFIG", str(settings))
    assert repo_project_label(project) == "demo"


def test_repo_project_label_oserror_falls_back(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    repo_dir = tmp_path / "standalone"
    repo_dir.mkdir()
    pygit2.init_repository(str(repo_dir), bare=False)
    monkeypatch.setattr(
        "pygittools.tui.project_label.load_pygitweb_layout",
        lambda: (_ for _ in ()).throw(OSError("missing")),
    )
    assert repo_project_label(repo_dir) == str(repo_dir.resolve())


@pytest.fixture
def repo(tmp_path: Path) -> pygit2.Repository:
    repo_path = tmp_path / "repo"
    repo_path.mkdir()
    return pygit2.init_repository(str(repo_path), bare=False)