"""Downloads and extracts platform-specific compiled checker bundles."""

import json
import logging
import os
import tarfile
import tempfile
from pathlib import Path
from urllib.request import urlopen, Request

from stablestack.checkers.loader import get_paid_checkers_dir

logger = logging.getLogger(__name__)


class DownloadError(Exception):
    """Raised when a checker bundle download or extraction fails."""
    pass


def download_checker_bundle(url: str) -> Path:
    """
    Download a compiled checker bundle .tar.gz from the given URL and extract
    it to ~/.stablestack/checkers/.

    Args:
        url: Pre-signed URL for the bundle download.

    Returns:
        Path to the checkers directory after extraction.

    Raises:
        DownloadError: If download or extraction fails.
    """
    checkers_dir = get_paid_checkers_dir()
    checkers_dir.mkdir(parents=True, exist_ok=True)

    try:
        # Download to a temporary file
        req = Request(url, headers={"User-Agent": "stablestack"})
        with tempfile.NamedTemporaryFile(
            suffix=".tar.gz", delete=False
        ) as tmp:
            tmp_path = tmp.name
            with urlopen(req, timeout=120) as resp:
                while True:
                    chunk = resp.read(8192)
                    if not chunk:
                        break
                    tmp.write(chunk)

        # Extract with path traversal protection
        _safe_extract(tmp_path, checkers_dir)

        # Verify manifest exists
        manifest_path = checkers_dir / "manifest.json"
        if not manifest_path.exists():
            raise DownloadError(
                "Bundle is missing manifest.json — download may be corrupt"
            )

        # Quick sanity check on manifest
        manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
        checker_count = len(manifest.get("checkers", []))
        logger.info(
            "Extracted %d paid checkers to %s", checker_count, checkers_dir
        )

        return checkers_dir

    except DownloadError:
        raise
    except Exception as e:
        raise DownloadError(f"Failed to download checker bundle: {e}") from e
    finally:
        # Clean up temp file
        try:
            os.unlink(tmp_path)
        except (OSError, UnboundLocalError):
            pass


def _safe_extract(tar_path: str, dest: Path) -> None:
    """Extract a tar.gz with path traversal protection."""
    dest_resolved = dest.resolve()

    with tarfile.open(tar_path, "r:gz") as tar:
        for member in tar.getmembers():
            member_path = (dest / member.name).resolve()
            # Path traversal check: every extracted file must stay inside dest
            if not str(member_path).startswith(str(dest_resolved)):
                raise DownloadError(
                    f"Path traversal detected in bundle: {member.name}"
                )
            # Block symlinks to prevent escaping the directory
            if member.issym() or member.islnk():
                raise DownloadError(
                    f"Symlink in bundle not allowed: {member.name}"
                )

        tar.extractall(path=str(dest))
