#!/usr/bin/env python3
"""
Test command line options for deb-bootc-image-builder.

This module tests command line argument parsing and validation,
including:
- Required arguments
- Optional arguments
- Argument validation
- Debian-specific options
"""

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 TestCommandLineOptions:
    """Test cases for command line options."""

    def test_required_arguments(self, work_dir):
        """Test required command line arguments."""
        # Test minimum required arguments
        required_args = {
            "container": "debian:trixie",
            "output": work_dir
        }
        
        # Validate required arguments
        for arg_name, arg_value in required_args.items():
            assert arg_value is not None, f"Required argument {arg_name} is None"
            if arg_name == "output":
                assert os.path.exists(arg_value), f"Output directory {arg_value} does not exist"

    def test_optional_arguments(self, work_dir):
        """Test optional command line arguments."""
        # Test optional arguments with default values
        optional_args = {
            "release": "trixie",
            "arch": "amd64",
            "image_type": "qcow2",
            "verbose": False,
            "clean": False
        }
        
        # Validate optional arguments
        for arg_name, arg_value in optional_args.items():
            assert arg_name in optional_args, f"Optional argument {arg_name} not found"
            assert arg_value is not None, f"Optional argument {arg_name} has no default value"

    def test_debian_specific_options(self, work_dir):
        """Test Debian-specific command line options."""
        # Test Debian-specific options
        debian_options = {
            "release": "trixie",
            "arch": "amd64",
            "package_manager": "apt",
            "initramfs_tools": True,
            "grub_efi": True
        }
        
        # Validate Debian-specific options
        assert debian_options["release"] in ["trixie", "bookworm", "bullseye"], \
            f"Invalid Debian release: {debian_options['release']}"
        
        assert debian_options["arch"] in ["amd64", "arm64", "i386"], \
            f"Invalid architecture: {debian_options['arch']}"
        
        assert debian_options["package_manager"] == "apt", \
            f"Invalid package manager: {debian_options['package_manager']}"
        
        assert debian_options["initramfs_tools"] is True, \
            "initramfs-tools should be enabled for Debian"
        
        assert debian_options["grub_efi"] is True, \
            "GRUB EFI should be enabled for Debian"

    def test_argument_validation(self, work_dir):
        """Test argument validation logic."""
        # Test valid arguments
        valid_args = {
            "container": "debian:trixie",
            "output": work_dir,
            "release": "trixie",
            "arch": "amd64"
        }
        
        validation_result = self._validate_arguments(valid_args)
        assert validation_result["valid"] is True, \
            f"Valid arguments failed validation: {validation_result.get('error', 'Unknown error')}"
        
        # Test invalid arguments
        invalid_args = {
            "container": "invalid:image",
            "output": "/nonexistent/path",
            "release": "invalid-release",
            "arch": "invalid-arch"
        }
        
        validation_result = self._validate_arguments(invalid_args)
        assert validation_result["valid"] is False, \
            "Invalid arguments should fail validation"

    def test_output_directory_handling(self, work_dir):
        """Test output directory handling."""
        # Test existing directory
        existing_dir = work_dir
        result = self._handle_output_directory(existing_dir)
        assert result["success"] is True, \
            f"Existing directory handling failed: {result.get('error', 'Unknown error')}"
        
        # Test non-existent directory creation
        new_dir = os.path.join(work_dir, "new_output")
        result = self._handle_output_directory(new_dir)
        assert result["success"] is True, \
            f"New directory creation failed: {result.get('error', 'Unknown error')}"
        assert os.path.exists(new_dir), "New directory was not created"
        
        # Test invalid directory path
        invalid_dir = "/invalid/path/with/permissions/issue"
        result = self._handle_output_directory(invalid_dir)
        assert result["success"] is False, "Invalid directory should fail"

    def test_container_image_validation(self, work_dir):
        """Test container image validation."""
        # Test valid Debian image
        valid_image = "debian:trixie"
        result = self._validate_container_image(valid_image)
        assert result["valid"] is True, \
            f"Valid Debian image failed validation: {result.get('error', 'Unknown error')}"
        
        # Test invalid image
        invalid_image = "invalid:image"
        result = self._validate_container_image(invalid_image)
        assert result["valid"] is False, "Invalid image should fail validation"
        
        # Test image with specific architecture
        arch_image = "debian:trixie-amd64"
        result = self._validate_container_image(arch_image)
        assert result["valid"] is True, \
            f"Architecture-specific image failed validation: {result.get('error', 'Unknown error')}"

    def test_package_list_validation(self, work_dir):
        """Test package list validation."""
        # Test valid Debian packages
        valid_packages = [
            "linux-image-amd64",
            "systemd",
            "ostree",
            "grub-efi-amd64",
            "initramfs-tools"
        ]
        
        result = self._validate_package_list(valid_packages)
        assert result["valid"] is True, \
            f"Valid packages failed validation: {result.get('error', 'Unknown error')}"
        
        # Test invalid packages
        invalid_packages = [
            "invalid-package",
            "nonexistent-package"
        ]
        
        result = self._validate_package_list(invalid_packages)
        assert result["valid"] is False, "Invalid packages should fail validation"

    def test_manifest_generation(self, work_dir):
        """Test manifest generation from command line options."""
        # Test manifest generation
        options = {
            "container": "debian:trixie",
            "release": "trixie",
            "arch": "amd64",
            "image_type": "qcow2",
            "packages": ["linux-image-amd64", "systemd", "ostree"]
        }
        
        manifest = self._generate_manifest(options)
        
        # Validate generated manifest
        assert "pipeline" in manifest
        assert "build" in manifest["pipeline"]
        assert "stages" in manifest["pipeline"]
        
        # Validate Debian-specific content
        build_stage = manifest["pipeline"]["build"]
        assert build_stage["name"] == "org.osbuild.debian-filesystem"
        
        # Validate APT stage
        apt_stage = next((s for s in manifest["pipeline"]["stages"] 
                         if s["name"] == "org.osbuild.apt"), None)
        assert apt_stage is not None
        assert apt_stage["options"]["release"] == "trixie"
        assert apt_stage["options"]["arch"] == "amd64"

    def _validate_arguments(self, args):
        """Mock argument validation."""
        # Check required arguments
        if "container" not in args or not args["container"]:
            return {"valid": False, "error": "Container image is required"}
        
        if "output" not in args or not args["output"]:
            return {"valid": False, "error": "Output directory is required"}
        
        # Check Debian-specific validation
        if "release" in args:
            valid_releases = ["trixie", "bookworm", "bullseye"]
            if args["release"] not in valid_releases:
                return {"valid": False, "error": f"Invalid Debian release: {args['release']}"}
        
        if "arch" in args:
            valid_archs = ["amd64", "arm64", "i386"]
            if args["arch"] not in valid_archs:
                return {"valid": False, "error": f"Invalid architecture: {args['arch']}"}
        
        return {"valid": True}

    def _handle_output_directory(self, output_dir):
        """Mock output directory handling."""
        try:
            if not os.path.exists(output_dir):
                os.makedirs(output_dir, exist_ok=True)
            
            # Test if directory is writable
            test_file = os.path.join(output_dir, "test_write")
            with open(test_file, 'w') as f:
                f.write("test")
            os.remove(test_file)
            
            return {"success": True}
        except Exception as e:
            return {"success": False, "error": str(e)}

    def _validate_container_image(self, image):
        """Mock container image validation."""
        # Check if it's a valid Debian image
        if image.startswith("debian:"):
            return {"valid": True, "type": "debian"}
        else:
            return {"valid": False, "error": "Not a valid Debian image"}

    def _validate_package_list(self, packages):
        """Mock package list validation."""
        # Check if packages look like valid Debian packages
        valid_packages = [
            "linux-image-amd64", "systemd", "ostree", "grub-efi-amd64",
            "initramfs-tools", "util-linux", "parted", "e2fsprogs"
        ]
        
        for pkg in packages:
            if pkg not in valid_packages:
                return {"valid": False, "error": f"Invalid package: {pkg}"}
        
        return {"valid": True}

    def _generate_manifest(self, options):
        """Mock manifest generation."""
        return {
            "pipeline": {
                "build": {
                    "name": "org.osbuild.debian-filesystem",
                    "options": {
                        "rootfs_type": "ext4",
                        "ostree_integration": True
                    }
                },
                "stages": [
                    {
                        "name": "org.osbuild.apt",
                        "options": {
                            "packages": options.get("packages", []),
                            "release": options.get("release", "trixie"),
                            "arch": options.get("arch", "amd64")
                        }
                    }
                ]
            }
        }


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