from pathlib import Path

from ..models import (
    CommandSpec,
    HarnessConfig,
    ProjectKind,
    ProjectSelection,
    Toolchain,
    ValidationPlan,
    ValidationStep,
)
from .base import AdapterError


def _test_argv(root: Path, command: tuple[str, ...]) -> tuple[str, ...]:
    if "/" not in command[0] and "\\" not in command[0]:
        return command
    first = Path(command[0].replace("\\", "/"))
    executable = first if first.is_absolute() else (root / first).resolve()
    try:
        executable.relative_to(root)
    except ValueError as exc:
        raise AdapterError(
            "msbuild.testCommand resolves outside the repository"
        ) from exc
    return (str(executable), *command[1:])


class MSBuildAdapter:
    def create_plan(
        self,
        root: Path,
        selection: ProjectSelection,
        config: HarnessConfig,
        tools: Toolchain,
    ) -> ValidationPlan:
        if selection.kind is not ProjectKind.MSBUILD:
            raise AdapterError("MSBuildAdapter received a non-MSBuild project")
        if not config.msbuild.test_command:
            raise AdapterError(
                "msbuild.testCommand is required for .sln/.vcxproj validation"
            )
        build = ValidationStep(
            CommandSpec(
                (
                    str(tools.msbuild),
                    str(selection.project_file),
                    "/m",
                    "/nologo",
                    f"/p:Configuration={config.msbuild.configuration}",
                    f"/p:Platform={config.msbuild.platform}",
                ),
                root,
                "build",
            )
        )
        test = ValidationStep(
            CommandSpec(_test_argv(root, config.msbuild.test_command), root, "test")
        )
        return ValidationPlan(ProjectKind.MSBUILD, (build, test))
