"""Tests related to role imports."""
from __future__ import annotations

from typing import TYPE_CHECKING

import pytest

from ansiblelint.runner import Runner

if TYPE_CHECKING:
    from pathlib import Path

    from _pytest.fixtures import SubRequest

    from ansiblelint.rules import RulesCollection

ROLE_TASKS_MAIN = """\
---
- name: Shell instead of command
  shell: echo hello world # noqa: fqcn no-free-form
  changed_when: false
"""

ROLE_TASKS_WORLD = """\
---
- ansible.builtin.debug:
    msg: "this is a task without a name"
"""

PLAY_IMPORT_ROLE = """\
---
- name: Test fixture
  hosts: all

  tasks:
    - name: Some import # noqa: fqcn
      import_role:
        name: test-role
"""

PLAY_IMPORT_ROLE_FQCN = """\
---
- name: Test fixture
  hosts: all

  tasks:
    - name: Some import
      ansible.builtin.import_role:
        name: test-role
"""

PLAY_IMPORT_ROLE_INLINE = """\
---
- name: Fixture
  hosts: all
  tasks:
    - name: Some import
      import_role: name=test-role  # noqa: no-free-form fqcn
"""

PLAY_INCLUDE_ROLE = """\
---
- name: Fixture
  hosts: all
  tasks:
    - name: Some import
      include_role:
        name: test-role
        tasks_from: world
"""

PLAY_INCLUDE_ROLE_FQCN = """\
---
- name: Fixture
  hosts: all
  tasks:
    - name: Some import
      ansible.builtin.include_role:
        name: test-role
        tasks_from: world
"""

PLAY_INCLUDE_ROLE_INLINE = """\
---
- name: Fixture
  hosts: all
  tasks:
    - name: Some import
      include_role: name=test-role tasks_from=world  # noqa: no-free-form
"""


@pytest.fixture(name="playbook_path")
def fixture_playbook_path(request: SubRequest, tmp_path: Path) -> str:
    """Create a reusable per-test role skeleton."""
    playbook_text = request.param
    role_tasks_dir = tmp_path / "test-role" / "tasks"
    role_tasks_dir.mkdir(parents=True)
    (role_tasks_dir / "main.yml").write_text(ROLE_TASKS_MAIN)
    (role_tasks_dir / "world.yml").write_text(ROLE_TASKS_WORLD)
    play_path = tmp_path / "playbook.yml"
    play_path.write_text(playbook_text)
    return str(play_path)


@pytest.mark.parametrize(
    ("playbook_path", "messages"),
    (
        pytest.param(
            PLAY_IMPORT_ROLE,
            ["only when shell functionality is required", "All tasks should be named"],
            id="IMPORT_ROLE",
        ),
        pytest.param(
            PLAY_IMPORT_ROLE_FQCN,
            ["only when shell functionality is required", "All tasks should be named"],
            id="IMPORT_ROLE_FQCN",
        ),
        pytest.param(
            PLAY_IMPORT_ROLE_INLINE,
            ["only when shell functionality is require", "All tasks should be named"],
            id="IMPORT_ROLE_INLINE",
        ),
        pytest.param(
            PLAY_INCLUDE_ROLE,
            ["only when shell functionality is require", "All tasks should be named"],
            id="INCLUDE_ROLE",
        ),
        pytest.param(
            PLAY_INCLUDE_ROLE_FQCN,
            ["only when shell functionality is require", "All tasks should be named"],
            id="INCLUDE_ROLE_FQCN",
        ),
        pytest.param(
            PLAY_INCLUDE_ROLE_INLINE,
            ["only when shell functionality is require", "All tasks should be named"],
            id="INCLUDE_ROLE_INLINE",
        ),
    ),
    indirect=("playbook_path",),
)
def test_import_role2(
    default_rules_collection: RulesCollection,
    playbook_path: str,
    messages: list[str],
) -> None:
    """Test that include_role digs deeper than import_role."""
    runner = Runner(
        playbook_path,
        rules=default_rules_collection,
        skip_list=["fqcn[action-core]"],
    )
    results = runner.run()
    for message in messages:
        assert message in str(results)
    # Ensure no other unexpected messages are present
    assert len(messages) == len(results), results
