"""Tests for editor helpers."""

from __future__ import annotations

import subprocess

import pytest

from metabranch.editor import _fallback_editor, _git_editor, _resolve_editor, edit_file
from metabranch.exceptions import EditorCancelledError


def test_edit_file_uses_git_editor_first(monkeypatch, tmp_path) -> None:
    editor_script = tmp_path / "editor.sh"
    editor_script.write_text("#!/bin/sh\necho edited > \"$1\"\n")
    editor_script.chmod(0o755)
    target = tmp_path / "plan.txt"

    monkeypatch.setattr("metabranch.editor._git_editor", lambda: str(editor_script))
    monkeypatch.delenv("GIT_EDITOR", raising=False)
    monkeypatch.delenv("VISUAL", raising=False)
    monkeypatch.delenv("EDITOR", raising=False)
    assert edit_file("initial\n", target) == "edited\n"


def test_git_editor_reads_local_git_config(monkeypatch, tmp_path) -> None:
    editor_script = tmp_path / "editor.sh"
    editor_script.write_text("#!/bin/sh\nexit 0\n")
    editor_script.chmod(0o755)

    monkeypatch.chdir(tmp_path)
    subprocess.run(["git", "init"], check=True, capture_output=True, text=True)
    subprocess.run(
        ["git", "config", "--local", "core.editor", str(editor_script)],
        check=True,
        capture_output=True,
        text=True,
    )

    assert _git_editor() == str(editor_script)


def test_git_editor_returns_none_without_local_config(monkeypatch, tmp_path) -> None:
    monkeypatch.chdir(tmp_path)
    subprocess.run(["git", "init"], check=True, capture_output=True, text=True)

    assert _git_editor() is None


@pytest.mark.parametrize("env_name", ["GIT_EDITOR", "VISUAL", "EDITOR"])
def test_resolve_editor_ignores_environment(monkeypatch, env_name: str) -> None:
    monkeypatch.setattr("metabranch.editor._git_editor", lambda: None)
    monkeypatch.setattr("metabranch.editor._fallback_editor", lambda: None)
    monkeypatch.setenv(env_name, f"{env_name.lower()}-value")

    assert _resolve_editor() is None


def test_resolve_editor_uses_terminal_fallback(monkeypatch) -> None:
    monkeypatch.setattr("metabranch.editor.shutil.which", lambda name: None)
    assert _fallback_editor() is None

    monkeypatch.setattr(
        "metabranch.editor.shutil.which",
        lambda name: "/usr/bin/vim" if name == "vim" else None,
    )
    assert _fallback_editor() == "/usr/bin/vim"

    monkeypatch.setattr("metabranch.editor._git_editor", lambda: None)
    monkeypatch.delenv("GIT_EDITOR", raising=False)
    monkeypatch.delenv("VISUAL", raising=False)
    monkeypatch.delenv("EDITOR", raising=False)
    monkeypatch.setattr("metabranch.editor._fallback_editor", lambda: "vim")

    assert _resolve_editor() == "vim"


def test_edit_file_handles_failure(monkeypatch, tmp_path) -> None:
    target = tmp_path / "plan.txt"
    failing_editor = tmp_path / "fail.sh"
    failing_editor.write_text("#!/bin/sh\nexit 1\n")
    failing_editor.chmod(0o755)
    monkeypatch.setattr("metabranch.editor._git_editor", lambda: str(failing_editor))

    with pytest.raises(EditorCancelledError, match="exited without saving"):
        edit_file("initial\n", target)


def test_edit_file_requires_editor(monkeypatch, tmp_path) -> None:
    target = tmp_path / "plan.txt"
    monkeypatch.setattr("metabranch.editor._git_editor", lambda: None)
    monkeypatch.setattr("metabranch.editor._fallback_editor", lambda: None)

    with pytest.raises(EditorCancelledError, match="Set git core.editor"):
        edit_file("initial\n", target)
