#!/usr/bin/env python3
"""
Test disk image building functionality for deb-bootc-image-builder.

This module tests the disk image building pipeline, including:
- Manifest validation
- Package installation
- Filesystem creation
- Bootloader configuration
"""

import pytest
import os
import tempfile
import shutil
import json
from unittest.mock import Mock, patch
import logging

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class TestDiskImageBuilding:
    """Test cases for disk image building functionality."""

    def test_manifest_validation(self, work_dir):
        """Test manifest validation for Debian images."""
        # Create a test manifest
        manifest = {
            "pipeline": {
                "build": {
                    "name": "org.osbuild.debian-filesystem",
                    "options": {
                        "rootfs_type": "ext4",
                        "ostree_integration": True
                    }
                },
                "stages": [
                    {
                        "name": "org.osbuild.apt",
                        "options": {
                            "packages": ["linux-image-amd64", "systemd"],
                            "release": "trixie",
                            "arch": "amd64"
                        }
                    }
                ]
            }
        }
        
        # Validate manifest structure
        assert "pipeline" in manifest
        assert "build" in manifest["pipeline"]
        assert "stages" in manifest["pipeline"]
        
        # Validate Debian-specific options
        build_stage = manifest["pipeline"]["build"]
        assert build_stage["name"] == "org.osbuild.debian-filesystem"
        assert build_stage["options"]["ostree_integration"] is True
        
        # Validate APT stage
        apt_stage = manifest["pipeline"]["stages"][0]
        assert apt_stage["name"] == "org.osbuild.apt"
        assert apt_stage["options"]["release"] == "trixie"
        assert "linux-image-amd64" in apt_stage["options"]["packages"]

    def test_debian_package_installation(self, work_dir):
        """Test Debian package installation pipeline."""
        # Mock package installation
        with patch('subprocess.run') as mock_run:
            mock_run.return_value.returncode = 0
            
            # Test package installation
            packages = ["linux-image-amd64", "systemd", "ostree"]
            result = self._install_packages(packages, work_dir)
            
            assert result is True
            mock_run.assert_called()

    def test_filesystem_creation(self, work_dir):
        """Test Debian filesystem creation."""
        # Test filesystem structure
        fs_structure = self._create_filesystem_structure(work_dir)
        
        expected_dirs = ["/etc", "/var", "/home", "/boot", "/usr"]
        for expected_dir in expected_dirs:
            full_path = os.path.join(work_dir, expected_dir.lstrip("/"))
            assert os.path.exists(full_path), f"Directory {expected_dir} not created"
        
        # Test /home -> /var/home symlink
        home_link = os.path.join(work_dir, "home")
        var_home = os.path.join(work_dir, "var", "home")
        assert os.path.islink(home_link), "/home symlink not created"
        assert os.path.realpath(home_link) == var_home

    def test_ostree_integration(self, work_dir):
        """Test OSTree integration setup."""
        # Test OSTree configuration
        ostree_config = self._setup_ostree_integration(work_dir)
        
        assert ostree_config["mode"] == "bare-user-only"
        assert ostree_config["repo"] == "/var/lib/ostree/repo"
        
        # Test OSTree repository creation
        repo_path = os.path.join(work_dir, "var", "lib", "ostree", "repo")
        assert os.path.exists(repo_path), "OSTree repository not created"

    def test_bootloader_configuration(self, work_dir):
        """Test GRUB bootloader configuration for Debian."""
        # Test GRUB configuration
        grub_config = self._configure_grub(work_dir)
        
        assert "GRUB_DEFAULT" in grub_config
        assert "GRUB_TIMEOUT" in grub_config
        assert "GRUB_CMDLINE_LINUX" in grub_config
        
        # Test UEFI boot configuration
        uefi_config = self._configure_uefi_boot(work_dir)
        assert uefi_config["uefi_enabled"] is True
        assert uefi_config["secure_boot"] is False

    def _install_packages(self, packages, work_dir):
        """Mock package installation."""
        # This would integrate with the actual APT stage
        logger.info(f"Installing packages: {packages}")
        return True

    def _create_filesystem_structure(self, work_dir):
        """Create basic filesystem structure."""
        dirs = ["etc", "var", "home", "boot", "usr", "usr/bin", "usr/lib", "usr/sbin"]
        for dir_path in dirs:
            full_path = os.path.join(work_dir, dir_path)
            os.makedirs(full_path, exist_ok=True)
        
        # Create /home -> /var/home symlink
        var_home = os.path.join(work_dir, "var", "home")
        os.makedirs(var_home, exist_ok=True)
        home_link = os.path.join(work_dir, "home")
        if os.path.exists(home_link):
            os.remove(home_link)
        os.symlink(var_home, home_link)
        
        return {"status": "created", "directories": dirs}

    def _setup_ostree_integration(self, work_dir):
        """Set up OSTree integration."""
        ostree_dir = os.path.join(work_dir, "var", "lib", "ostree", "repo")
        os.makedirs(ostree_dir, exist_ok=True)
        
        config = {
            "mode": "bare-user-only",
            "repo": "/var/lib/ostree/repo"
        }
        
        # Write OSTree configuration
        config_file = os.path.join(work_dir, "etc", "ostree", "ostree.conf")
        os.makedirs(os.path.dirname(config_file), exist_ok=True)
        
        with open(config_file, 'w') as f:
            f.write("[core]\n")
            f.write(f"mode={config['mode']}\n")
            f.write(f"repo={config['repo']}\n")
        
        return config

    def _configure_grub(self, work_dir):
        """Configure GRUB bootloader."""
        grub_config = {
            "GRUB_DEFAULT": "0",
            "GRUB_TIMEOUT": "5",
            "GRUB_CMDLINE_LINUX": "console=ttyS0,115200n8 console=tty0"
        }
        
        # Write GRUB configuration
        grub_dir = os.path.join(work_dir, "etc", "default")
        os.makedirs(grub_dir, exist_ok=True)
        
        grub_file = os.path.join(grub_dir, "grub")
        with open(grub_file, 'w') as f:
            for key, value in grub_config.items():
                f.write(f'{key}="{value}"\n')
        
        return grub_config

    def _configure_uefi_boot(self, work_dir):
        """Configure UEFI boot."""
        uefi_config = {
            "uefi_enabled": True,
            "secure_boot": False,
            "boot_entries": ["debian", "debian-fallback"]
        }
        
        # Create UEFI boot directory
        efi_dir = os.path.join(work_dir, "boot", "efi", "EFI", "debian")
        os.makedirs(efi_dir, exist_ok=True)
        
        return uefi_config


if __name__ == "__main__":
    pytest.main([__file__])
