# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2026 The MVT Authors.
# Use of this software is governed by the MVT License 1.1 that can be found at
#   https://license.mvt.re/1.1/

"""Helpers building throwaway plugin distributions for the tests.

Some plugin behaviour only shows up in a fresh interpreter: what an import
executes, and what a plugin sees when MVT is imported before or after it.
These helpers write an importable distribution with a real entry point and
run a script against it in a subprocess, with a temporary home so that the
subprocess cannot touch the configuration of whoever runs the tests.
"""

import os
import subprocess
import sys
from pathlib import Path
from typing import Optional

FIXTURE_COMMAND_NAME = "fixture-plugin"
FIXTURE_MODULE_NAME = "fixture_cli_plugin"
FIXTURE_DISTRIBUTION_NAME = "fixture-cli-plugin"


def write_cli_plugin_distribution(
    site_path: Path,
    entry_point_group: str,
    module_source: str,
) -> Path:
    """Write a distribution registering a CLI plugin entry point.

    :param site_path: Folder to write the distribution into, to be added to
                      the import path of the interpreter loading it.
    :param entry_point_group: Entry-point group to register the command in.
    :param module_source: Source of the plugin module, which must define a
                          Click command named `cli`.
    :returns: The folder the distribution was written to.
    """
    site_path.mkdir(parents=True, exist_ok=True)
    (site_path / f"{FIXTURE_MODULE_NAME}.py").write_text(
        module_source, encoding="utf-8"
    )

    dist_info = (
        site_path / f"{FIXTURE_DISTRIBUTION_NAME.replace('-', '_')}-1.0.dist-info"
    )
    dist_info.mkdir(exist_ok=True)
    (dist_info / "METADATA").write_text(
        f"Metadata-Version: 2.1\nName: {FIXTURE_DISTRIBUTION_NAME}\nVersion: 1.0\n",
        encoding="utf-8",
    )
    (dist_info / "entry_points.txt").write_text(
        f"[{entry_point_group}]\n{FIXTURE_COMMAND_NAME} = {FIXTURE_MODULE_NAME}:cli\n",
        encoding="utf-8",
    )
    return site_path


def run_isolated_python(
    script: str,
    home: Path,
    site_path: Optional[Path] = None,
    **environment: str,
) -> subprocess.CompletedProcess:
    """Run a script in a fresh interpreter with its own configuration folder.

    Importing MVT writes its configuration file, so the subprocess gets a
    temporary home and no MVT environment variables from the test session.
    """
    isolated_environment = {
        key: value for key, value in os.environ.items() if not key.startswith("MVT_")
    }
    isolated_environment["HOME"] = str(home)
    isolated_environment["XDG_CONFIG_HOME"] = str(home / "config")
    if site_path is not None:
        isolated_environment["PYTHONPATH"] = str(site_path)
    isolated_environment.update(environment)

    return subprocess.run(
        [sys.executable, "-c", script],
        capture_output=True,
        text=True,
        env=isolated_environment,
    )
