"""Tests for downloader module."""

import tarfile
import tempfile
import zipfile
from pathlib import Path
from unittest.mock import patch

import pytest

from cve_extractor.core import download_and_extract_cve_data


@pytest.fixture
def mock_archive(tmp_path: Path) -> Path:
    """Create mock tarball archive with nested ZIP and cves directory structure."""
    # Create cves subdirectory structure
    cves_dir = tmp_path / "cves"
    cves_dir.mkdir()

    # Create test files
    test_file = cves_dir / "test.json"
    test_file.write_text('{"test": "data"}')

    # Create nested ZIP
    inner_zip = cves_dir / "inner.zip"
    with zipfile.ZipFile(inner_zip, "w") as zf:
        zf.write(test_file, "test.json")

    # Create tarball with wrapper directory (like GitHub)
    archive = tmp_path / "test.tar.gz"
    with tarfile.open(archive, "w:gz") as tf:
        # Add files under a root directory (like GitHub's cvelistV5-{hash}/)
        tf.add(cves_dir, arcname="cvelistV5-test123/cves")

    return archive


def test_download_and_extract_cve_data(tmp_path: Path, mock_archive: Path) -> None:
    """Test downloading and extracting CVE data from GitHub commit."""
    cache_dir = tmp_path / "cache"
    target_dir = tmp_path / "target"

    with patch("cve_extractor.core.downloader._download_github_tarball") as mock_download:
        # Mock download to copy our test archive
        def copy_archive(owner: str, repo: str, commit_hash: str, dest_path: Path) -> None:
            import shutil

            shutil.copy(mock_archive, dest_path)

        mock_download.side_effect = copy_archive

        result = download_and_extract_cve_data(
            "a218727",
            cache_dir,
            target_dir,
        )

        assert result == target_dir
        assert target_dir.exists()

        # Check that cves directory exists
        assert (target_dir / "cves").exists()
        
        # Check nested extraction
        json_files = list(target_dir.rglob("*.json"))
        assert len(json_files) > 0


def test_download_with_invalid_commit_hash(tmp_path: Path) -> None:
    """Test with invalid commit hash."""
    cache_dir = tmp_path / "cache"
    target_dir = tmp_path / "target"

    with pytest.raises(ValueError, match="commit_hash cannot be empty"):
        download_and_extract_cve_data("", cache_dir, target_dir)
