#!/usr/bin/env python3
"""
Test the test utilities for deb-bootc-image-builder.

This module tests the test utility functions and classes,
including:
- Test data generation
- Mock objects
- Helper functions
- Debian-specific utilities
"""

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

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


class TestTestUtilities:
    """Test cases for test utility functions and classes."""

    def test_test_data_generator(self, work_dir):
        """Test the TestDataGenerator class."""
        from testutil import TestDataGenerator
        
        # Test Debian package list generation
        packages = TestDataGenerator.create_debian_package_list()
        assert isinstance(packages, list)
        assert len(packages) > 0
        
        # Check for essential Debian packages
        essential_packages = ["linux-image-amd64", "systemd", "ostree"]
        for pkg in essential_packages:
            assert pkg in packages, f"Essential package {pkg} missing"
        
        # Test repository configuration
        repo_config = TestDataGenerator.create_debian_repository_config()
        assert "release" in repo_config
        assert "arch" in repo_config
        assert "repos" in repo_config
        assert repo_config["release"] == "trixie"
        assert repo_config["arch"] == "amd64"
        
        # Test OSTree configuration
        ostree_config = TestDataGenerator.create_ostree_config()
        assert "mode" in ostree_config
        assert "repo" in ostree_config
        assert ostree_config["mode"] == "bare-user-only"
        
        # Test GRUB configuration
        grub_config = TestDataGenerator.create_grub_config()
        assert "uefi" in grub_config
        assert "timeout" in grub_config
        assert grub_config["uefi"] is True

    def test_mock_container_image(self, work_dir):
        """Test the MockContainerImage class."""
        from testutil import MockContainerImage
        
        # Test default labels
        image = MockContainerImage()
        labels = image.get_labels()
        
        assert "com.debian.bootc" in labels
        assert "ostree.bootable" in labels
        assert labels["com.debian.bootc"] == "true"
        assert labels["ostree.bootable"] == "true"
        
        # Test custom labels
        custom_labels = {
            "com.debian.bootc": "true",
            "version": "2.0",
            "custom.label": "value"
        }
        image = MockContainerImage(custom_labels)
        
        assert image.get_labels() == custom_labels
        assert image.get_ref() == "debian:trixie"
        assert image.get_arch() == "amd64"
        assert image.get_os() == "linux"

    def test_mock_ostree_repo(self, work_dir):
        """Test the MockOSTreeRepo class."""
        from testutil import MockOSTreeRepo
        
        # Test repository creation
        repo = MockOSTreeRepo("/tmp/test-repo")
        
        assert repo.path == "/tmp/test-repo"
        assert len(repo.list_refs()) > 0
        assert "debian/trixie/amd64" in repo.list_refs()
        
        # Test deployment info
        deployment_info = repo.get_deployment_info("debian/trixie/amd64")
        assert deployment_info is not None
        assert deployment_info["ref"] == "debian/trixie/amd64"
        assert deployment_info["osname"] == "debian"
        assert deployment_info["bootable"] is True
        
        # Test non-existent deployment
        non_existent = repo.get_deployment_info("non-existent")
        assert non_existent is None

    def test_test_environment(self, work_dir):
        """Test the TestEnvironment class."""
        from testutil import TestEnvironment
        
        # Create test environment
        env = TestEnvironment(work_dir)
        
        # Test setup
        env.setup()
        
        # Check that directories were created
        expected_dirs = ["etc", "var", "home", "boot", "usr", "var/lib", "var/lib/ostree", "var/home"]
        for expected_dir in expected_dirs:
            full_path = os.path.join(work_dir, expected_dir)
            assert os.path.exists(full_path), f"Directory {expected_dir} not created"
        
        # Check /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
        
        # Test file creation
        test_file = env.create_test_file("test.txt", "test content")
        assert os.path.exists(test_file)
        
        with open(test_file, 'r') as f:
            content = f.read()
        assert content == "test content"
        
        # Test directory creation
        test_dir = env.create_test_directory("test_dir")
        assert os.path.exists(test_dir)
        assert os.path.isdir(test_dir)
        
        # Test teardown
        env.teardown()
        # Note: teardown only changes directory, doesn't remove files

    def test_utility_functions(self, work_dir):
        """Test utility functions."""
        from testutil import (
            create_temp_manifest,
            cleanup_temp_files,
            assert_filesystem_structure,
            assert_file_contents,
            create_mock_context
        )
        
        # Test manifest creation
        manifest_data = {
            "pipeline": {
                "build": {"name": "test"},
                "stages": []
            }
        }
        
        manifest_file = create_temp_manifest(manifest_data)
        assert os.path.exists(manifest_file)
        
        # Test manifest loading
        with open(manifest_file, 'r') as f:
            loaded_data = json.load(f)
        assert loaded_data == manifest_data
        
        # Test cleanup
        cleanup_temp_files(manifest_file)
        assert not os.path.exists(manifest_file)
        
        # Test filesystem structure assertion
        test_dir = os.path.join(work_dir, "test_structure")
        os.makedirs(test_dir, exist_ok=True)
        os.makedirs(os.path.join(test_dir, "etc"), exist_ok=True)
        os.makedirs(os.path.join(test_dir, "var"), exist_ok=True)
        
        assert_filesystem_structure(test_dir, ["/etc", "/var"])
        
        # Test file contents assertion
        test_file = os.path.join(test_dir, "test.txt")
        with open(test_file, 'w') as f:
            f.write("test content")
        
        assert_file_contents(test_file, "test content")
        
        # Test mock context creation
        context = create_mock_context()
        assert context.root == "/tmp/mock-root"
        assert hasattr(context, 'run')
        
        # Test mock context run method
        result = context.run("test command")
        assert result.returncode == 0
        assert result.stdout == b"mock output"

    def test_debian_specific_utilities(self, work_dir):
        """Test Debian-specific utility functions."""
        from testutil import TestDataGenerator
        
        # Test Debian filesystem configuration
        fs_config = TestDataGenerator.create_filesystem_config()
        
        assert "rootfs_type" in fs_config
        assert "ostree_integration" in fs_config
        assert "home_symlink" in fs_config
        assert "users" in fs_config
        assert "permissions" in fs_config
        
        assert fs_config["rootfs_type"] == "ext4"
        assert fs_config["ostree_integration"] is True
        assert fs_config["home_symlink"] is True
        
        # Test user configuration
        users = fs_config["users"]
        assert len(users) > 0
        assert "name" in users[0]
        assert "password" in users[0]
        assert "groups" in users[0]
        
        # Test permission configuration
        permissions = fs_config["permissions"]
        assert "/etc/ostree" in permissions
        assert "/var/lib/ostree" in permissions
        assert permissions["/etc/ostree"] == "755"

    def test_error_handling(self, work_dir):
        """Test error handling in utility functions."""
        from testutil import cleanup_temp_files, assert_file_contents
        
        # Test cleanup with non-existent file
        cleanup_temp_files("/non/existent/file")
        # Should not raise an exception
        
        # Test file contents assertion with non-existent file
        with pytest.raises(AssertionError):
            assert_file_contents("/non/existent/file", "content")

    def test_performance_utilities(self, work_dir):
        """Test performance-related utilities."""
        from testutil import create_mock_context
        
        # Test multiple context creation
        start_time = time.time()
        contexts = []
        
        for i in range(100):
            context = create_mock_context()
            contexts.append(context)
        
        end_time = time.time()
        creation_time = end_time - start_time
        
        # Should be reasonably fast
        assert creation_time < 1.0, f"Context creation took too long: {creation_time}s"
        assert len(contexts) == 100
        
        # Test context functionality
        for context in contexts:
            result = context.run("test")
            assert result.returncode == 0


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