from __future__ import annotations

from pathlib import Path
from unittest.mock import MagicMock

import pytest
from pygit2 import Repository, init_repository

from pygittools.tui.git_worktrees import (
    add_worktree,
    list_worktrees,
    parse_worktree_porcelain,
    remove_worktree,
)


def test_parse_worktree_porcelain() -> None:
    text = """
worktree /repo/main
HEAD abcdef1234567890
branch refs/heads/main

worktree /repo/feature
HEAD 1111111111111111
branch refs/heads/feature
locked

worktree /repo/old
prunable gitdir file points to non-existent location

""".strip()
    entries = parse_worktree_porcelain(text)
    assert len(entries) == 3
    assert entries[0].path == Path("/repo/main")
    assert entries[0].branch == "main"
    assert entries[0].head == "abcdef1234567890"
    assert entries[1].locked == ""
    assert entries[1].branch == "feature"
    assert entries[2].prunable == "gitdir file points to non-existent location"


def test_parse_detached_and_bare() -> None:
    text = """
worktree /repo/detached
HEAD deadbeef
detached

worktree /repo/bare.git
bare

""".strip()
    entries = parse_worktree_porcelain(text)
    assert entries[0].detached is True
    assert entries[0].branch is None
    assert entries[1].bare is True


def test_list_worktrees_no_workdir(monkeypatch: pytest.MonkeyPatch) -> None:
    repo = MagicMock(spec=Repository)
    repo.workdir = None
    entries, error = list_worktrees(repo)
    assert entries == []
    assert error is not None


def test_add_worktree_requires_path(repo: Repository, monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[list[str]] = []

    def fake_run(cmd: list[str], **kwargs: object) -> MagicMock:
        calls.append(cmd)
        return MagicMock(returncode=0, stdout="", stderr="")

    monkeypatch.setattr("pygittools.tui.git_worktrees.subprocess.run", fake_run)
    ok, error = add_worktree(repo, Path("../wt"), "feature")
    assert ok is True
    assert error == ""
    assert calls
    assert "-b" in calls[0] or "feature" in calls[0]


def test_remove_worktree_force(repo: Repository, monkeypatch: pytest.MonkeyPatch) -> None:
    calls: list[list[str]] = []

    def fake_run(cmd: list[str], **kwargs: object) -> MagicMock:
        calls.append(cmd)
        return MagicMock(returncode=0, stdout="", stderr="")

    monkeypatch.setattr("pygittools.tui.git_worktrees.subprocess.run", fake_run)
    ok, error = remove_worktree(repo, Path("/tmp/wt"), force=True)
    assert ok is True
    assert "--force" in calls[0]


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