"""Pytest fixtures wiring the httpd test framework together.

Session scope: probe httpd -> generate config -> compile C modules -> start
server, then stop it at the end. Function scope: an HTTP client and a vhost
resolver. Mirrors the orchestration Apache::TestRun performs.

Requirement markers (need_module, need_min_apache_version, need_cgi, need_php,
need_ssl, need_lwp) declared via apache_pytest.testapi are evaluated at
collection time against a one-time probe of the target httpd, skipping tests
whose requirements aren't met -- the analog of Apache::Test's plan-time skips.

CLI options:
  --httpd   path to the httpd binary (default: derived from --apxs SBINDIR)
  --apxs    path to apxs (used to locate httpd + the inherited install conf,
            and to build the C modules)
  --defines space-separated extra -D defines (e.g. 'LDAP')
"""

from __future__ import annotations

import subprocess
from pathlib import Path

import pytest

from apache_pytest import HttpdServer, TestClient, TestConfig, compile_all, probe
from apache_pytest.cmodules import clean_modules
from apache_pytest.probe import HttpdInfo

# The suite is self-contained: all assets it needs (t/conf templates, t/htdocs
# docroot, c-modules sources, auth files) live under this directory (python/).
# SUITE_ROOT is therefore this file's directory -- nothing outside it is read.
SUITE_ROOT = Path(__file__).resolve().parent
# Backwards-compatible alias (older code referenced REPO_ROOT).
REPO_ROOT = SUITE_ROOT


def pytest_addoption(parser: pytest.Parser) -> None:
    group = parser.getgroup("httpd")
    group.addoption("--httpd", action="store", default=None, help="path to httpd binary")
    group.addoption("--apxs", action="store", default=None, help="path to apxs")
    group.addoption(
        "--defines",
        action="store",
        default="",
        help="space-separated extra -D defines (e.g. 'LDAP')",
    )
    group.addoption(
        "--php-fpm",
        action="store",
        default=None,
        help="path to a php-fpm binary; enables the t/php tests via mod_proxy_fcgi "
        "(any version/location -- the path is the only PHP-specific input)",
    )
    group.addoption(
        "--php-fpm-port",
        action="store",
        type=int,
        default=8999,
        help="TCP port for the managed php-fpm pool (default 8999)",
    )
    group.addoption(
        "--clean-modules",
        action="store_true",
        default=False,
        help="remove all compiled C-module artifacts before building (emulate make clean)",
    )
    group.addoption(
        "--conf",
        action="store",
        default=None,
        help="path to the installed httpd.conf (for LoadModule discovery "
        "when --apxs is not available, e.g. on Windows)",
    )
    group.addoption(
        "--prefix",
        action="store",
        default=None,
        help="server install prefix for resolving relative module paths "
        "(default: derived from --conf path)",
    )
    group.addoption(
        "--with-perl",
        action="store",
        default=None,
        help="path to the perl interpreter for generated scripts and "
        "rewrite prg-maps (default: /usr/bin/perl or APACHE_TEST_PERL env)",
    )


def pytest_configure(config: pytest.Config) -> None:
    for marker in (
        "need_module(*names): skip unless all named httpd modules are available",
        "need_min_apache_version(ver): skip unless server >= ver",
        "need_cgi(): skip unless a CGI module is available",
        "need_php(): skip unless a PHP SAPI module is available",
        "need_ssl(): skip unless mod_ssl is available",
        "need_lwp(): always satisfied (httpx client always present)",
    ):
        config.addinivalue_line("markers", marker)


def _apxs_query(apxs: Path, var: str) -> str:
    proc = subprocess.run(  # noqa: S603 - trusted path
        ["perl", str(apxs), "-q", var], capture_output=True, text=True, check=True
    )
    return proc.stdout.strip()


class _NoServerError(Exception):
    """Raised when neither --httpd nor --apxs was provided."""


def _resolve_paths(
    config: pytest.Config,
) -> tuple[Path, Path | None, Path | None, Path | None, list[str]]:
    """Resolve (httpd, apxs, inherited_conf, install_prefix, defines) from options.

    Raises :class:`_NoServerError` if neither --httpd nor --apxs is given. (A
    plain exception, not pytest.fail, so the collection-time probe can catch it
    without turning into an INTERNALERROR; the fixture converts it to a clean
    skip/fail at setup time.)
    """
    apxs_opt = config.getoption("--apxs")
    httpd_opt = config.getoption("--httpd")
    defines = [d for d in config.getoption("--defines").split() if d]

    apxs = Path(apxs_opt) if apxs_opt else None
    inherited_conf: Path | None = None
    install_prefix: Path | None = None
    if apxs is not None:
        sbindir = Path(_apxs_query(apxs, "SBINDIR"))
        sysconfdir = Path(_apxs_query(apxs, "SYSCONFDIR"))
        install_prefix = Path(_apxs_query(apxs, "PREFIX"))
        inherited_conf = sysconfdir / "httpd.conf"
        if httpd_opt is None:
            httpd_opt = str(sbindir / "httpd")

    conf_opt = config.getoption("--conf")
    prefix_opt = config.getoption("--prefix")
    if conf_opt is not None and inherited_conf is None:
        inherited_conf = Path(conf_opt)
    if prefix_opt is not None:
        install_prefix = Path(prefix_opt)
    elif inherited_conf is not None and install_prefix is None:
        install_prefix = inherited_conf.parent.parent

    if httpd_opt is None:
        raise _NoServerError("must pass --httpd or --apxs")
    return Path(httpd_opt), apxs, inherited_conf, install_prefix, defines


# --------------------------------------------------------------------------- #
# Collection-time requirement gating (need_* markers)
# --------------------------------------------------------------------------- #
_probe_cache: HttpdInfo | None = None


def _probed_info(config: pytest.Config) -> HttpdInfo | None:
    """Probe the target httpd once for collection-time requirement checks.

    Returns None if no httpd was specified (so requirement markers can't be
    evaluated -- tests are left to fail/skip naturally at fixture setup).
    """
    global _probe_cache  # noqa: PLW0603 - simple memo across the collection hook
    if _probe_cache is not None:
        return _probe_cache
    try:
        httpd, _apxs, inherited_conf, install_prefix, _defines = _resolve_paths(config)
    except Exception:
        return None
    info = probe(httpd, inherited_conf, install_prefix)
    # The bundled C test modules (authany, echo_post, input_body_filter, ...) are
    # compiled and LoadModule'd into the generated test config by the session
    # fixture, so need_module("authany") etc. should be satisfied at collection
    # time too. Augment the probed set with the C modules that WILL be built
    # (honoring the same HTTPD_TEST_REQUIRE_APACHE gating discover() applies).
    from apache_pytest.cmodules import discover

    cmods, _skipped = discover(REPO_ROOT / "c-modules", info)
    for mod in cmods:
        info.modules.add(f"mod_{mod.name}.c")
    _probe_cache = info
    return _probe_cache


def _unmet_requirement(
    item: pytest.Item, info: HttpdInfo, *, php_fpm: bool = False
) -> str | None:
    """Return a skip reason if any need_* marker on ``item`` is unmet, else None.

    ``php_fpm`` indicates a php-fpm binary was provided (and mod_proxy_fcgi is
    available), which satisfies need_php even without an in-process PHP SAPI.
    """
    for mark in item.iter_markers(name="need_module"):
        for name in mark.args:
            if not info.has_module(name):
                return f"module {name} not available"
    for mark in item.iter_markers(name="need_min_apache_version"):
        ver = mark.args[0]
        parts = tuple(int(x) for x in str(ver).split("."))
        parts += (0,) * (3 - len(parts))
        if info.version < parts:
            return f"httpd {info.version_str} < required {ver}"
    if any(item.iter_markers(name="need_cgi")) and not (
        info.has_module("mod_cgi") or info.has_module("mod_cgid")
    ):
        return "no CGI module (mod_cgi/mod_cgid) available"
    if any(item.iter_markers(name="need_php")):
        php_mods = ("sapi_apache2", "mod_php4", "mod_php5", "mod_php7", "mod_php")
        have_sapi = any(info.has_module(m) for m in php_mods)
        have_fpm = php_fpm and info.has_module("mod_proxy_fcgi")
        if not (have_sapi or have_fpm):
            return "no PHP SAPI module or php-fpm available"
    if any(item.iter_markers(name="need_ssl")) and not info.has_module("mod_ssl"):
        return "mod_ssl not available"
    # need_lwp is always satisfied (httpx is always present); no check.
    return None


def pytest_collection_modifyitems(
    config: pytest.Config, items: list[pytest.Item]
) -> None:
    info = _probed_info(config)
    if info is None:
        return
    php_fpm = bool(config.getoption("--php-fpm"))
    for item in items:
        reason = _unmet_requirement(item, info, php_fpm=php_fpm)
        if reason:
            item.add_marker(pytest.mark.skip(reason=reason))


# --------------------------------------------------------------------------- #
# Server lifecycle + client fixtures
# --------------------------------------------------------------------------- #
@pytest.fixture(scope="session")
def framework(request: pytest.FixtureRequest):
    """Probe, configure, build C modules, start httpd; yield (config, server)."""
    try:
        httpd, apxs, inherited_conf, install_prefix, defines = _resolve_paths(request.config)
    except _NoServerError as exc:
        pytest.fail(str(exc))

    info = probe(httpd, inherited_conf, install_prefix)

    perl_opt = request.config.getoption("--with-perl")
    if perl_opt:
        import os
        os.environ["APACHE_TEST_PERL"] = perl_opt

    # Optional PHP-FPM: if a php-fpm binary was given and mod_proxy_fcgi is
    # available, route htdocs/php/*.php to a managed FPM daemon. The php-fpm
    # path/port are the only PHP-specific inputs -- no version is assumed.
    php_fpm_opt = request.config.getoption("--php-fpm")
    fpm_port = int(request.config.getoption("--php-fpm-port"))
    fpm_mgr = None
    use_fpm = bool(php_fpm_opt) and info.has_module("mod_proxy_fcgi")

    config = TestConfig(
        info=info,
        top_dir=REPO_ROOT,
        defines=defines,
        apxs=apxs,
        fpm_port=fpm_port if use_fpm else None,
    )

    cmodule_loads: list[tuple[str, Path]] = []
    if apxs is not None:
        cmodules_dir = REPO_ROOT / "c-modules"
        if request.config.getoption("--clean-modules"):
            clean_modules(cmodules_dir)
        cmodule_loads, _skipped = compile_all(
            cmodules_dir, apxs, info, defines=["APACHE2", "APACHE2_4", *defines]
        )
    else:
        from apache_pytest.cmodules import discover
        modules_dir = (install_prefix / "modules") if install_prefix else httpd.parent
        cmods, _skipped = discover(REPO_ROOT / "c-modules", info)
        for mod in cmods:
            so = modules_dir / f"mod_{mod.name}.so"
            if so.exists():
                cmodule_loads.append((mod.symbol, so))

    config.generate(cmodule_loads=cmodule_loads)

    if use_fpm:
        from apache_pytest.fpm import PhpFpm

        fpm_mgr = PhpFpm(
            Path(php_fpm_opt),
            run_dir=Path(config.vars["t_logs"]) / "php-fpm",
            port=fpm_port,
        )
        fpm_mgr.start()

    # Record the error_log size right before this session's httpd starts.
    # error_log is opened in append mode and t_logs/ is not cleaned between
    # invocations, so it can carry entries from earlier, unrelated test runs
    # (possibly hours/days old, with different pids). Tests that need "since
    # this server session started" (as opposed to "since this individual
    # test started") must scope their log reads to this offset, not to
    # position 0 -- see test_proxy_beacon.py.
    error_log = Path(config.vars["t_logs"]) / "error_log"
    config.vars["session_log_start"] = str(
        error_log.stat().st_size if error_log.exists() else 0
    )

    server = HttpdServer(config)
    server.start()
    try:
        yield config, server
    finally:
        server.stop()
        if fpm_mgr is not None:
            fpm_mgr.stop()


@pytest.fixture(scope="session")
def config(framework) -> TestConfig:
    return framework[0]


@pytest.fixture(scope="session")
def server(framework) -> HttpdServer:
    return framework[1]


@pytest.fixture
def http(config: TestConfig):
    """Function-scoped HTTP client bound to the running server."""
    client = TestClient(config)
    try:
        yield client
    finally:
        client.close()
