from __future__ import annotations

import asyncio
import subprocess
from pathlib import Path

from loushang.coding.control import ControlConfig, SettingsManager
from loushang.coding.loader import DefaultResourceLoader
from loushang.coding.package import PackageMaterializer, PythonPackageInstallerBackend
from loushang.coding.session.package_controller import PackageController
from loushang.coding.store import SessionManager


def test_package_controller_installs_local_package_updates_settings_and_refreshes_once(tmp_path) -> None:
    local_package = tmp_path / "local-pack"
    local_package.mkdir()
    settings = SettingsManager(ControlConfig())
    materializer = PackageMaterializer(install_root=tmp_path / "packages")
    resource_loader = DefaultResourceLoader()
    refreshes: list[str] = []

    controller = PackageController(
        session_manager=SessionManager.new(session_dir=tmp_path, cwd=str(tmp_path), persist=False),
        get_settings_manager=lambda: settings,
        get_package_materializer=lambda: materializer,
        get_resource_loader=lambda: resource_loader,
        get_diagnostics_service=lambda: None,
        refresh_resources=lambda: refreshes.append("refresh"),
    )

    result = asyncio.run(controller.install_package(str(local_package), scope="project"))

    assert result["lifecycle"] == "installed"
    assert result["targetPath"] == str(local_package.resolve())
    assert [package.source for package in settings.get_package_sources()] == [str(local_package)]
    assert refreshes == ["refresh"]


def test_package_controller_installs_python_package_updates_settings_and_refreshes_once(tmp_path) -> None:
    settings = SettingsManager(ControlConfig())
    resource_loader = DefaultResourceLoader()
    refreshes: list[str] = []

    def runner(args: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]:
        target = Path(args[args.index("--target") + 1])
        dist_info = target / "acme_review_pack-1.2.3.dist-info"
        dist_info.mkdir(parents=True)
        (dist_info / "METADATA").write_text("Name: acme-review-pack\nVersion: 1.2.3\n", encoding="utf-8")
        (target / "prompts").mkdir()
        (target / "prompts" / "review.md").write_text("Review prompt.", encoding="utf-8")
        return subprocess.CompletedProcess(args, 0, "", "")

    materializer = PackageMaterializer(
        install_root=tmp_path / "packages",
        python_backend=PythonPackageInstallerBackend(runner=runner),
    )
    controller = PackageController(
        session_manager=SessionManager.new(session_dir=tmp_path, cwd=str(tmp_path), persist=False),
        get_settings_manager=lambda: settings,
        get_package_materializer=lambda: materializer,
        get_resource_loader=lambda: resource_loader,
        get_diagnostics_service=lambda: None,
        refresh_resources=lambda: refreshes.append("refresh"),
    )

    result = asyncio.run(controller.install_package("pypi:acme-review-pack==1.2.3", scope="project"))

    assert result["lifecycle"] == "installed"
    assert result["sourceType"] == "python"
    assert result["installer"] == "uv"
    assert result["resolvedName"] == "acme-review-pack"
    assert result["resolvedVersion"] == "1.2.3"
    assert [package.source for package in settings.get_package_sources()] == ["pypi:acme-review-pack==1.2.3"]
    assert refreshes == ["refresh"]
