from __future__ import annotations

import shutil
from pathlib import Path

import pytest

from juist.justfiles.loader import JuistLoader
from juist.justfiles.models import Scope

DATA_JUSTFILE = Path(__file__).parent / "data" / "justfile"

SIMPLE_JUSTFILE = """\
# Do something
hello:
    echo hello
"""

ANOTHER_JUSTFILE = """\
# Do another thing
world:
    echo world
"""


@pytest.fixture
def tmp_home(tmp_path: Path) -> Path:
    return tmp_path / "juist_home"


@pytest.fixture
def tmp_cwd(tmp_path: Path) -> Path:
    return tmp_path / "project"


def _write_justfile(path: Path, content: str) -> Path:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content)
    return path


def test_load_empty(tmp_home, tmp_cwd):
    tmp_cwd.mkdir()
    config = JuistLoader().load(cwd=tmp_cwd, juist_home=tmp_home)
    assert config.global_sources == []
    assert config.local_sources == []


def test_load_global_root_justfile(tmp_home, tmp_cwd):
    tmp_cwd.mkdir()
    _write_justfile(tmp_home / "justfile", SIMPLE_JUSTFILE)

    config = JuistLoader().load(cwd=tmp_cwd, juist_home=tmp_home)

    assert len(config.global_sources) == 1
    assert config.global_sources[0].name == "justfile"
    assert config.global_sources[0].scope == Scope.global_
    assert config.local_sources == []


def test_load_local_root_justfile(tmp_home, tmp_cwd):
    tmp_cwd.mkdir()
    _write_justfile(tmp_cwd / "justfile", SIMPLE_JUSTFILE)

    config = JuistLoader().load(cwd=tmp_cwd, juist_home=tmp_home)

    assert config.global_sources == []
    assert len(config.local_sources) == 1
    assert config.local_sources[0].name == "justfile"
    assert config.local_sources[0].scope == Scope.local


def test_load_global_just_files(tmp_home, tmp_cwd):
    tmp_cwd.mkdir()
    _write_justfile(tmp_home / "ops.just", SIMPLE_JUSTFILE)
    _write_justfile(tmp_home / "dev.just", ANOTHER_JUSTFILE)

    config = JuistLoader().load(cwd=tmp_cwd, juist_home=tmp_home)

    names = {s.name for s in config.global_sources}
    assert names == {"ops", "dev"}
    assert all(s.scope == Scope.global_ for s in config.global_sources)


def test_load_local_just_files(tmp_home, tmp_cwd):
    tmp_cwd.mkdir()
    _write_justfile(tmp_cwd / ".juist" / "ci.just", SIMPLE_JUSTFILE)

    config = JuistLoader().load(cwd=tmp_cwd, juist_home=tmp_home)

    assert config.global_sources == []
    assert len(config.local_sources) == 1
    assert config.local_sources[0].name == "ci"
    assert config.local_sources[0].scope == Scope.local


def test_load_with_real_fixture(tmp_home, tmp_cwd):
    tmp_cwd.mkdir()
    shutil.copy(DATA_JUSTFILE, tmp_cwd / "justfile")

    config = JuistLoader().load(cwd=tmp_cwd, juist_home=tmp_home)

    assert len(config.local_sources) == 1
    source = config.local_sources[0]
    assert source.scope == Scope.local
    recipe_names = {r.name for r in source.recipes}
    assert recipe_names == {"bootstrap", "upgrade-deps", "script1", "script2"}
