"""Smoke test: build the wheel, install it, activate a license, scan files, find issues.

This is a TRUE end-to-end test. It:
1. Builds the wheel from source
2. Installs it in a fresh temp venv
3. Activates a real license key against the real API
4. Creates files with known security violations
5. Runs `stablestack check` via the CLI
6. Asserts that specific rule IDs appear in the JSON output

This catches packaging bugs (missing files in wheel), broken __init__.py
imports, and CLI/checker integration issues that unit tests miss.

Marked @pytest.mark.slow — skipped by default, run with: pytest -m slow
"""

import json
import subprocess
import sys
import textwrap

import pytest


def _stablestack_root():
    """Return the stablestack/ package directory."""
    from pathlib import Path
    return Path(__file__).resolve().parent.parent


def _build_and_install(tmp_path):
    """Build wheel, create venv, install. Returns venv python path."""
    result = subprocess.run(
        [sys.executable, "-m", "build", "--wheel", "--outdir", str(tmp_path / "dist")],
        cwd=str(_stablestack_root()),
        capture_output=True,
        text=True,
        timeout=120,
    )
    assert result.returncode == 0, f"Build failed:\n{result.stderr}"

    whl_files = list((tmp_path / "dist").glob("*.whl"))
    assert len(whl_files) == 1, f"Expected 1 wheel, got {whl_files}"

    venv_dir = tmp_path / "venv"
    subprocess.run(
        [sys.executable, "-m", "venv", str(venv_dir)],
        check=True,
        timeout=30,
    )
    venv_python = str(venv_dir / "bin" / "python")

    subprocess.run(
        [venv_python, "-m", "pip", "install", str(whl_files[0]), "certifi", "--quiet"],
        check=True,
        capture_output=True,
        timeout=120,
    )

    # Get the CA bundle path from certifi inside the venv
    cert_result = subprocess.run(
        [venv_python, "-c", "import certifi; print(certifi.where())"],
        capture_output=True,
        text=True,
        timeout=10,
    )
    ca_bundle = cert_result.stdout.strip()

    return venv_python, venv_dir, ca_bundle


# The test license key for StableStack Team (enterprise, unlimited, expires 2027)
_TEST_LICENSE_KEY = (
    "sk_live_2e5d5a9215c660750f822a848af1e049"
)


@pytest.mark.slow
class TestWheelSmoke:
    """Full end-to-end: build wheel -> install -> activate -> scan -> find issues."""

    def test_end_to_end(self, tmp_path):
        """The entire stablestack flow works from an installed wheel."""
        _venv_python, venv_dir, ca_bundle = _build_and_install(tmp_path)
        stablestack = str(venv_dir / "bin" / "stablestack")

        # ── 1. Activate license key ───────────────────────────────
        result = subprocess.run(
            [stablestack, "activate", _TEST_LICENSE_KEY],
            capture_output=True,
            text=True,
            timeout=30,
            env={
                **_clean_env(ca_bundle),
                "HOME": str(tmp_path / "home"),
                "DO_NOT_TRACK": "1",
            },
        )
        # Activation should succeed (license is valid in DynamoDB)
        assert result.returncode == 0, (
            f"Activation failed:\nstdout: {result.stdout}\nstderr: {result.stderr}"
        )
        assert "License valid" in result.stdout, (
            f"Expected 'License valid' in output:\n{result.stdout}"
        )

        # ── 3. Create project dir with known-bad files ────────────
        project_dir = tmp_path / "test_project"
        project_dir.mkdir()

        # SEC001: hardcoded secret
        (project_dir / "config.py").write_text(textwrap.dedent("""\
            API_KEY = "sk_live_abc123def456ghi789"
            DATABASE_URL = "postgresql://user:password@localhost/db"
        """))

        # SEC012: NODE_ENV security gate (free tier, should always fire)
        (project_dir / "webhook.ts").write_text(textwrap.dedent("""\
            export function handleWebhook(req: Request) {
                if (process.env.NODE_ENV === "production" && webhookSecret) {
                    verifySignature(req);
                }
                processPayload(req.body);
            }
        """))

        # SEC002: SQL injection
        (project_dir / "db.py").write_text(textwrap.dedent("""\
            def get_user(user_id):
                query = f"SELECT * FROM users WHERE id = '{user_id}'"
                cursor.execute(query)
        """))

        # ── 4. Run stablestack check with JSON output ─────────────
        result = subprocess.run(
            [stablestack, "check", str(project_dir), "--format", "json", "--quiet"],
            capture_output=True,
            text=True,
            timeout=30,
            env={
                **_clean_env(ca_bundle),
                "HOME": str(tmp_path / "home"),
                "DO_NOT_TRACK": "1",
                "STABLESTACK_NO_TELEMETRY": "1",
            },
        )

        # ── 5. Parse output and verify findings ──────────────────
        # --quiet gives summary line on stdout; JSON goes to stdout too
        # Let's also try without --quiet for JSON
        result = subprocess.run(
            [stablestack, "check", str(project_dir), "--format", "json"],
            capture_output=True,
            text=True,
            timeout=30,
            env={
                **_clean_env(ca_bundle),
                "HOME": str(tmp_path / "home"),
                "DO_NOT_TRACK": "1",
                "STABLESTACK_NO_TELEMETRY": "1",
            },
        )

        # JSON output should be parseable
        # stderr has the "Warning: Unlicensed" banner, stdout has JSON
        stdout = result.stdout.strip()
        assert stdout, f"No output from stablestack check:\nstderr: {result.stderr}"

        data = json.loads(stdout)
        # JSON format wraps findings in {"findings": [...], "summary": {...}}
        findings = data.get("findings", data) if isinstance(data, dict) else data
        assert isinstance(findings, list), f"Expected list, got {type(findings)}: {data}"
        assert len(findings) > 0, "No findings — checkers didn't detect known-bad code"

        rule_ids_found = {f["rule_id"] for f in findings}

        # These are free-tier checks that MUST fire on our test files
        assert "SEC001" in rule_ids_found, (
            f"SEC001 (hardcoded secret) not found. Got: {rule_ids_found}"
        )
        assert "SEC002" in rule_ids_found, (
            f"SEC002 (SQL injection) not found. Got: {rule_ids_found}"
        )
        assert "SEC012" in rule_ids_found, (
            f"SEC012 (NODE_ENV security gate) not found. Got: {rule_ids_found}"
        )

        # Verify finding structure
        for f in findings:
            assert "rule_id" in f
            assert "file" in f
            assert "line" in f
            assert "message" in f

    def test_package_imports(self, tmp_path):
        """Every free-tier package __init__.py imports cleanly from the wheel."""
        venv_python, _, _ca = _build_and_install(tmp_path)

        # Test that package-level imports work (catches __init__.py importing
        # paid modules that are excluded from the wheel)
        script = textwrap.dedent("""\
            import sys
            errors = []

            packages = [
                "stablestack.checkers",
                "stablestack.checkers.security",
                "stablestack.checkers.session",
                "stablestack.checkers.project",
                "stablestack.checkers.quality",
                "stablestack.checkers.structure",
                "stablestack.checkers.schema",
            ]

            for mod in packages:
                try:
                    __import__(mod)
                except ImportError as e:
                    errors.append(f"  {mod}: {e}")

            from stablestack.checkers import FREE_CHECKERS
            if len(FREE_CHECKERS) == 0:
                errors.append("  FREE_CHECKERS is empty")

            if errors:
                print("IMPORT FAILURES:\\n" + "\\n".join(errors))
                sys.exit(1)
            print(f"OK: {len(packages)} packages, {len(FREE_CHECKERS)} free checkers")
        """)

        result = subprocess.run(
            [venv_python, "-c", script],
            capture_output=True,
            text=True,
            timeout=30,
        )
        assert result.returncode == 0, (
            f"Package imports failed:\n{result.stdout}\n{result.stderr}"
        )


def _clean_env(ca_bundle=""):
    """Return a minimal clean environment for subprocess calls."""
    import os
    env = {
        "PATH": os.environ.get("PATH", "/usr/bin:/bin:/usr/local/bin"),
        "LANG": os.environ.get("LANG", "en_US.UTF-8"),
        "TERM": "dumb",
    }
    # Set SSL cert path so HTTPS works in the temp venv
    if ca_bundle:
        env["SSL_CERT_FILE"] = ca_bundle
    # Pass through any existing SSL env vars as fallback
    for key in ("SSL_CERT_FILE", "SSL_CERT_DIR", "REQUESTS_CA_BUNDLE",
                "CURL_CA_BUNDLE"):
        if key in os.environ and key not in env:
            env[key] = os.environ[key]
    return env
