"""Tests for implementation folder management utilities."""

import json
from datetime import UTC, datetime
from pathlib import Path

import pytest

from erk_shared.gateway.github.issues.fake import FakeGitHubIssues
from erk_shared.gateway.github.issues.types import IssueInfo
from erk_shared.gateway.github.metadata.core import (
    find_metadata_block,
    parse_metadata_blocks,
)
from erk_shared.impl_folder import (
    IMPL_DIR_RELATIVE,
    _sanitize_branch_for_dirname,
    add_worktree_creation_comment,
    create_impl_folder,
    get_impl_dir,
    get_impl_path,
    has_plan_ref,
    read_last_dispatched_run_id,
    read_plan_author,
    read_plan_ref,
    resolve_impl_dir,
    save_plan_ref,
    validate_plan_linkage,
)

BRANCH = "feature/test-branch"
"""Test branch name used across tests."""

# =============================================================================
# get_impl_dir / _sanitize_branch_for_dirname Tests
# =============================================================================


def test_sanitize_branch_simple() -> None:
    """Test sanitizing a branch name without slashes."""
    assert _sanitize_branch_for_dirname("main") == "main"


def test_sanitize_branch_with_slash() -> None:
    """Test sanitizing a branch name with slashes."""
    assert _sanitize_branch_for_dirname("feature/test-branch") == "feature--test-branch"


def test_sanitize_branch_multiple_slashes() -> None:
    """Test sanitizing a branch name with multiple slashes."""
    assert _sanitize_branch_for_dirname("refs/heads/feature") == "refs--heads--feature"


def test_get_impl_dir_basic(tmp_path: Path) -> None:
    """Test get_impl_dir returns correct path."""
    result = get_impl_dir(tmp_path, branch_name="feature/test")
    assert result == tmp_path / IMPL_DIR_RELATIVE / "feature--test"


def test_get_impl_dir_no_slash(tmp_path: Path) -> None:
    """Test get_impl_dir with branch name without slash."""
    result = get_impl_dir(tmp_path, branch_name="main")
    assert result == tmp_path / IMPL_DIR_RELATIVE / "main"


# =============================================================================
# create_impl_folder Tests
# =============================================================================


def test_create_impl_folder_basic(tmp_path: Path) -> None:
    """Test creating an impl folder with basic plan content."""
    plan_content = """# Implementation Plan: Test Feature

## Objective
Build a test feature.

## Tasks
1. Create module
2. Add tests
3. Update documentation
"""
    plan_folder = create_impl_folder(tmp_path, plan_content, branch_name=BRANCH, overwrite=False)

    # Verify folder structure
    assert plan_folder.exists()
    assert plan_folder == get_impl_dir(tmp_path, branch_name=BRANCH)

    # Verify plan.md exists and has correct content
    plan_file = plan_folder / "plan.md"
    assert plan_file.exists()
    assert plan_file.read_text(encoding="utf-8") == plan_content


def test_create_impl_folder_already_exists(tmp_path: Path) -> None:
    """Test that creating a plan folder when one exists raises error."""
    plan_content = "# Test Plan\n"

    # Create first time - should succeed
    create_impl_folder(tmp_path, plan_content, branch_name=BRANCH, overwrite=False)

    # Try to create again - should raise
    with pytest.raises(FileExistsError, match="Implementation folder already exists"):
        create_impl_folder(tmp_path, plan_content, branch_name=BRANCH, overwrite=False)


def test_create_impl_folder_overwrite_replaces_existing(tmp_path: Path) -> None:
    """Test that overwrite=True removes existing impl folder before creating new one."""
    old_plan = "# Old Plan\n\nOld content.\n"
    new_plan = "# New Plan\n\nNew content.\n"

    # Create first impl folder
    impl_folder = create_impl_folder(tmp_path, old_plan, branch_name=BRANCH, overwrite=False)
    old_plan_file = impl_folder / "plan.md"

    # Verify old content
    assert old_plan_file.read_text(encoding="utf-8") == old_plan

    # Create again with overwrite=True - should succeed and replace content
    new_impl_folder = create_impl_folder(tmp_path, new_plan, branch_name=BRANCH, overwrite=True)

    # Verify new content replaced old
    assert new_impl_folder == impl_folder  # Same path
    new_plan_file = new_impl_folder / "plan.md"

    assert new_plan_file.read_text(encoding="utf-8") == new_plan

    # Verify old content is gone
    assert "Old" not in new_plan_file.read_text(encoding="utf-8")


def test_get_impl_path_exists(tmp_path: Path) -> None:
    """Test getting plan path when it exists."""
    plan_content = "# Test\n"
    create_impl_folder(tmp_path, plan_content, branch_name=BRANCH, overwrite=False)

    plan_path = get_impl_path(tmp_path, branch_name=BRANCH)
    assert plan_path is not None
    assert plan_path == get_impl_dir(tmp_path, branch_name=BRANCH) / "plan.md"
    assert plan_path.exists()


def test_get_impl_path_not_exists(tmp_path: Path) -> None:
    """Test getting plan path when it doesn't exist."""
    plan_path = get_impl_path(tmp_path, branch_name=BRANCH)
    assert plan_path is None


# ============================================================================
# Worktree Creation Comment Tests
# ============================================================================


def test_add_worktree_creation_comment_success(tmp_path: Path) -> None:
    """Test posting GitHub comment documenting worktree creation."""
    # Create fake GitHub issues with an existing issue
    issues = FakeGitHubIssues(
        issues={
            42: IssueInfo(
                number=42,
                title="Test Issue",
                body="Test body",
                state="OPEN",
                url="https://github.com/owner/repo/issues/42",
                labels=["erk-pr", "erk-plan"],
                assignees=[],
                created_at=datetime.now(UTC),
                updated_at=datetime.now(UTC),
                author="test-user",
            )
        }
    )

    # Post comment
    add_worktree_creation_comment(
        github_issues=issues,
        repo_root=tmp_path,
        plan_number=42,
        worktree_name="feature-name",
        branch_name="feature-branch",
    )

    # Verify comment was added
    assert len(issues.added_comments) == 1
    issue_number, comment_body, _comment_id = issues.added_comments[0]

    # Verify comment details
    assert issue_number == 42
    assert "✅ Worktree created: **feature-name**" in comment_body
    assert "erk br co feature-branch" in comment_body
    assert "/erk:plan-implement" in comment_body

    # Round-trip verification: Parse metadata block back out
    result = parse_metadata_blocks(comment_body)
    assert len(result.blocks) == 1

    block = find_metadata_block(comment_body, "erk-worktree-creation")
    assert block is not None
    assert block.key == "erk-worktree-creation"
    assert block.data["worktree_name"] == "feature-name"
    assert block.data["branch_name"] == "feature-branch"
    assert block.data["plan_number"] == 42
    assert "timestamp" in block.data
    assert isinstance(block.data["timestamp"], str)
    assert len(block.data["timestamp"]) > 0

    # Verify timestamp format (ISO 8601 UTC)
    assert "T" in block.data["timestamp"]  # ISO 8601 includes 'T' separator
    assert ":" in block.data["timestamp"]  # ISO 8601 includes ':' in time


def test_add_worktree_creation_comment_issue_not_found(tmp_path: Path) -> None:
    """Test add_worktree_creation_comment raises error when issue doesn't exist."""
    issues = FakeGitHubIssues(issues={})  # No issues

    # Should raise RuntimeError (simulating gh CLI error)
    with pytest.raises(RuntimeError, match="Issue #999 not found"):
        add_worktree_creation_comment(
            github_issues=issues,
            repo_root=tmp_path,
            plan_number=999,
            worktree_name="feature-name",
            branch_name="feature-branch",
        )


# ============================================================================
# Plan Author Attribution Tests
# ============================================================================


def test_read_plan_author_success(tmp_path: Path) -> None:
    """Test reading plan author from plan.md with valid plan-header block."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md with plan-header metadata block
    plan_content = """<!-- WARNING: Machine-generated. Manual edits may break erk tooling. -->
<!-- erk:metadata-block:plan-header -->
<details>
<summary><code>plan-header</code></summary>

```yaml

schema_version: '2'
created_at: '2025-01-15T10:00:00+00:00'
created_by: test-user
worktree_name: test-worktree

```

</details>
<!-- /erk:metadata-block:plan-header -->

# Test Plan

1. Step one
2. Step two
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    # Read author
    author = read_plan_author(impl_dir)

    assert author == "test-user"


def test_read_plan_author_no_plan_file(tmp_path: Path) -> None:
    """Test read_plan_author returns None when plan.md doesn't exist."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    author = read_plan_author(impl_dir)

    assert author is None


def test_read_plan_author_no_impl_dir(tmp_path: Path) -> None:
    """Test read_plan_author returns None when impl directory doesn't exist."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    # Don't create the directory

    author = read_plan_author(impl_dir)

    assert author is None


def test_read_plan_author_no_metadata_block(tmp_path: Path) -> None:
    """Test read_plan_author returns None when plan.md has no plan-header block."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md without metadata block
    plan_content = """# Simple Plan

1. Step one
2. Step two
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    author = read_plan_author(impl_dir)

    assert author is None


def test_read_plan_author_missing_created_by_field(tmp_path: Path) -> None:
    """Test read_plan_author returns None when created_by field is missing."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md with plan-header but no created_by
    plan_content = """<!-- WARNING: Machine-generated. Manual edits may break erk tooling. -->
<!-- erk:metadata-block:plan-header -->
<details>
<summary><code>plan-header</code></summary>

```yaml

schema_version: '2'
created_at: '2025-01-15T10:00:00+00:00'
worktree_name: test-worktree

```

</details>
<!-- /erk:metadata-block:plan-header -->
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    author = read_plan_author(impl_dir)

    assert author is None


# ============================================================================
# Last Dispatched Run ID Tests
# ============================================================================


def test_read_last_dispatched_run_id_success(tmp_path: Path) -> None:
    """Test reading run ID from plan.md with valid plan-header block."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md with plan-header metadata block including run ID
    plan_content = """<!-- WARNING: Machine-generated. Manual edits may break erk tooling. -->
<!-- erk:metadata-block:plan-header -->
<details>
<summary><code>plan-header</code></summary>

```yaml

schema_version: '2'
created_at: '2025-01-15T10:00:00+00:00'
created_by: test-user
worktree_name: test-worktree
last_dispatched_run_id: '12345678901'
last_dispatched_at: '2025-01-15T11:00:00+00:00'

```

</details>
<!-- /erk:metadata-block:plan-header -->

# Test Plan

1. Step one
2. Step two
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    # Read run ID
    run_id = read_last_dispatched_run_id(impl_dir)

    assert run_id == "12345678901"


def test_read_last_dispatched_run_id_no_plan_file(tmp_path: Path) -> None:
    """Test read_last_dispatched_run_id returns None when plan.md doesn't exist."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    run_id = read_last_dispatched_run_id(impl_dir)

    assert run_id is None


def test_read_last_dispatched_run_id_no_impl_dir(tmp_path: Path) -> None:
    """Test read_last_dispatched_run_id returns None when impl directory doesn't exist."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    # Don't create the directory

    run_id = read_last_dispatched_run_id(impl_dir)

    assert run_id is None


def test_read_last_dispatched_run_id_no_metadata_block(tmp_path: Path) -> None:
    """Test read_last_dispatched_run_id returns None when plan.md has no plan-header block."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md without metadata block
    plan_content = """# Simple Plan

1. Step one
2. Step two
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    run_id = read_last_dispatched_run_id(impl_dir)

    assert run_id is None


def test_read_last_dispatched_run_id_null_value(tmp_path: Path) -> None:
    """Test read_last_dispatched_run_id returns None when run ID is null."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md with plan-header but null run ID
    plan_content = """<!-- WARNING: Machine-generated. Manual edits may break erk tooling. -->
<!-- erk:metadata-block:plan-header -->
<details>
<summary><code>plan-header</code></summary>

```yaml

schema_version: '2'
created_at: '2025-01-15T10:00:00+00:00'
created_by: test-user
worktree_name: test-worktree
last_dispatched_run_id: null
last_dispatched_at: null

```

</details>
<!-- /erk:metadata-block:plan-header -->
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    run_id = read_last_dispatched_run_id(impl_dir)

    assert run_id is None


def test_read_last_dispatched_run_id_missing_field(tmp_path: Path) -> None:
    """Test read_last_dispatched_run_id returns None when run ID field is missing."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Create plan.md with plan-header but no last_dispatched_run_id
    plan_content = """<!-- WARNING: Machine-generated. Manual edits may break erk tooling. -->
<!-- erk:metadata-block:plan-header -->
<details>
<summary><code>plan-header</code></summary>

```yaml

schema_version: '2'
created_at: '2025-01-15T10:00:00+00:00'
created_by: test-user
worktree_name: test-worktree

```

</details>
<!-- /erk:metadata-block:plan-header -->
"""
    plan_file = impl_dir / "plan.md"
    plan_file.write_text(plan_content, encoding="utf-8")

    run_id = read_last_dispatched_run_id(impl_dir)

    assert run_id is None


# ============================================================================
# PlanRef Storage Tests
# ============================================================================


def test_save_plan_ref_success(tmp_path: Path) -> None:
    """Test saving plan reference to ref.json."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="42",
        url="https://github.com/owner/repo/issues/42",
        labels=("erk-plan",),
        objective_id=99,
        node_ids=None,
    )

    ref_file = impl_dir / "ref.json"
    assert ref_file.exists()

    data = json.loads(ref_file.read_text(encoding="utf-8"))
    assert data["provider"] == "github"
    assert data["plan_id"] == "42"
    assert data["url"] == "https://github.com/owner/repo/issues/42"
    assert data["labels"] == ["erk-plan"]
    assert data["objective_id"] == 99
    assert "created_at" in data
    assert "synced_at" in data


def test_save_plan_ref_dir_not_exists(tmp_path: Path) -> None:
    """Test save_plan_ref raises error when dir doesn't exist."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)

    with pytest.raises(FileNotFoundError, match="Implementation directory does not exist"):
        save_plan_ref(
            impl_dir,
            provider="github",
            plan_id="42",
            url="http://url",
            labels=(),
            objective_id=None,
            node_ids=None,
        )


def test_save_plan_ref_no_objective(tmp_path: Path) -> None:
    """Test save_plan_ref stores null for objective_id when None."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="42",
        url="http://url",
        labels=(),
        objective_id=None,
        node_ids=None,
    )

    data = json.loads((impl_dir / "ref.json").read_text(encoding="utf-8"))
    assert data["objective_id"] is None


def test_read_plan_ref_roundtrip(tmp_path: Path) -> None:
    """Test save -> read roundtrip for plan-ref.json."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="42",
        url="https://github.com/owner/repo/issues/42",
        labels=("erk-pr", "erk-learn"),
        objective_id=99,
        node_ids=None,
    )

    ref = read_plan_ref(impl_dir)
    assert ref is not None
    assert ref.provider == "github"
    assert ref.plan_id == "42"
    assert ref.url == "https://github.com/owner/repo/issues/42"
    assert ref.labels == ("erk-pr", "erk-learn")
    assert ref.objective_id == 99
    assert len(ref.created_at) > 0
    assert len(ref.synced_at) > 0


def test_read_plan_ref_prefers_ref_json(tmp_path: Path) -> None:
    """Test read_plan_ref prefers ref.json over legacy issue.json."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    # Write both files with different data
    ref_data = {
        "provider": "linear",
        "plan_id": "PROJ-123",
        "url": "https://linear.app/proj/PROJ-123",
        "created_at": "2025-01-15T10:00:00+00:00",
        "synced_at": "2025-01-15T10:00:00+00:00",
        "labels": [],
        "objective_id": None,
    }
    (impl_dir / "ref.json").write_text(json.dumps(ref_data), encoding="utf-8")

    issue_data = {
        "issue_number": 42,
        "issue_url": "https://github.com/owner/repo/issues/42",
        "created_at": "2025-01-15T10:00:00+00:00",
        "synced_at": "2025-01-15T10:00:00+00:00",
    }
    (impl_dir / "issue.json").write_text(json.dumps(issue_data), encoding="utf-8")

    ref = read_plan_ref(impl_dir)
    assert ref is not None
    assert ref.provider == "linear"
    assert ref.plan_id == "PROJ-123"


def test_read_plan_ref_not_exists(tmp_path: Path) -> None:
    """Test read_plan_ref returns None when no files exist."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    ref = read_plan_ref(impl_dir)
    assert ref is None


def test_read_plan_ref_invalid_json(tmp_path: Path) -> None:
    """Test read_plan_ref returns None for invalid JSON."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    (impl_dir / "ref.json").write_text("not valid json", encoding="utf-8")

    ref = read_plan_ref(impl_dir)
    assert ref is None


def test_read_plan_ref_missing_fields(tmp_path: Path) -> None:
    """Test read_plan_ref returns None when required fields missing."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    (impl_dir / "ref.json").write_text(json.dumps({"provider": "github"}), encoding="utf-8")

    ref = read_plan_ref(impl_dir)
    assert ref is None


def test_has_plan_ref_with_ref_json(tmp_path: Path) -> None:
    """Test has_plan_ref detects ref.json."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="42",
        url="http://url",
        labels=(),
        objective_id=None,
        node_ids=None,
    )

    assert has_plan_ref(impl_dir) is True


def test_has_plan_ref_not_exists(tmp_path: Path) -> None:
    """Test has_plan_ref returns False when neither file exists."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)

    assert has_plan_ref(impl_dir) is False


# ============================================================================
# Plan Linkage Validation Tests (PlanRef-based)
# ============================================================================


def test_validate_plan_linkage_both_match(tmp_path: Path) -> None:
    """Test validation passes when branch and ref.json match."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)
    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="42",
        url="https://github.com/org/repo/issues/42",
        labels=(),
        objective_id=None,
        node_ids=None,
    )

    result = validate_plan_linkage(impl_dir, "P42-add-feature-01-04-1234")
    assert result == "42"


def test_validate_plan_linkage_mismatch_raises(tmp_path: Path) -> None:
    """Test validation returns plan_id from plan-ref when branch has no issue number.

    P-prefix branches cannot provide an issue number to validate against.
    The function returns the plan_id from plan-ref.json without any mismatch check.
    """
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)
    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="99",
        url="https://github.com/org/repo/issues/99",
        labels=(),
        objective_id=None,
        node_ids=None,
    )

    # No longer raises - branch provides no issue number, so no mismatch possible
    result = validate_plan_linkage(impl_dir, "P42-add-feature-01-04-1234")
    assert result == "99"  # Returns plan_id from plan-ref.json


def test_validate_plan_linkage_branch_only(tmp_path: Path) -> None:
    """Test validation returns None when no plan ref exists and branch has no issue number.

    P-prefix branches cannot provide an issue number. With no plan-ref.json,
    the function returns None.
    """
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)

    result = validate_plan_linkage(impl_dir, "P123-some-feature-01-04-1234")
    assert result is None  # Branch no longer provides issue number


def test_validate_plan_linkage_impl_only(tmp_path: Path) -> None:
    """Test validation returns plan_id when branch has no issue number."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)
    save_plan_ref(
        impl_dir,
        provider="github",
        plan_id="456",
        url="https://github.com/org/repo/issues/456",
        labels=(),
        objective_id=None,
        node_ids=None,
    )

    result = validate_plan_linkage(impl_dir, "main")
    assert result == "456"


def test_validate_plan_linkage_neither(tmp_path: Path) -> None:
    """Test validation returns None when neither source has info."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)

    result = validate_plan_linkage(impl_dir, "feature-branch")
    assert result is None


def test_validate_plan_linkage_planned_pr_with_plan_ref(tmp_path: Path) -> None:
    """Test planned-PR branch returns plan_id from plan-ref.json."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)
    impl_dir.mkdir(parents=True)
    save_plan_ref(
        impl_dir,
        provider="github-draft-pr",
        plan_id="789",
        url="https://github.com/org/repo/pull/789",
        labels=(),
        objective_id=None,
        node_ids=None,
    )

    result = validate_plan_linkage(impl_dir, "plan-fix-auth-bug-01-15-1430")
    assert result == "789"


def test_validate_plan_linkage_planned_pr_without_plan_ref(tmp_path: Path) -> None:
    """Test planned-PR branch without plan-ref.json returns None."""
    impl_dir = get_impl_dir(tmp_path, branch_name=BRANCH)

    result = validate_plan_linkage(impl_dir, "plan-fix-auth-bug-01-15-1430")
    assert result is None


# ============================================================================
# resolve_impl_dir Tests
# ============================================================================


def test_resolve_impl_dir_branch_scoped(tmp_path: Path) -> None:
    """Test resolve_impl_dir finds branch-scoped directory."""
    create_impl_folder(tmp_path, "# Plan\n", branch_name=BRANCH, overwrite=False)

    result = resolve_impl_dir(tmp_path, branch_name=BRANCH)
    assert result is not None
    assert result == get_impl_dir(tmp_path, branch_name=BRANCH)


def test_resolve_impl_dir_discovery(tmp_path: Path) -> None:
    """Test resolve_impl_dir discovers subdir via plan.md search."""
    # Create a branch-scoped dir for a different branch
    other_branch = "other/feature"
    create_impl_folder(tmp_path, "# Plan\n", branch_name=other_branch, overwrite=False)

    # Searching with a branch that doesn't have its own dir should discover via scan
    result = resolve_impl_dir(tmp_path, branch_name="nonexistent-branch")
    assert result is not None
    assert result == get_impl_dir(tmp_path, branch_name=other_branch)


def test_resolve_impl_dir_not_found(tmp_path: Path) -> None:
    """Test resolve_impl_dir returns None when nothing found."""
    result = resolve_impl_dir(tmp_path, branch_name="nonexistent-branch")
    assert result is None


def test_resolve_impl_dir_branch_scoped_priority(tmp_path: Path) -> None:
    """Test resolve_impl_dir prefers branch-scoped over legacy .impl/."""
    # Create both branch-scoped and legacy directories
    create_impl_folder(tmp_path, "# Branch Plan\n", branch_name=BRANCH, overwrite=False)
    legacy_dir = tmp_path / ".impl"
    legacy_dir.mkdir()
    (legacy_dir / "plan.md").write_text("# Legacy Plan\n", encoding="utf-8")

    result = resolve_impl_dir(tmp_path, branch_name=BRANCH)
    assert result is not None
    assert result == get_impl_dir(tmp_path, branch_name=BRANCH)
