#!/usr/bin/env python3
"""
Test flake8 compliance for deb-bootc-image-builder.

This module tests code style compliance using flake8,
including:
- PEP 8 compliance
- Code style validation
- Debian-specific style standards
"""

import pytest
import os
import tempfile
import shutil
import subprocess
import logging

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


class TestFlake8Compliance:
    """Test cases for flake8 compliance."""

    def test_flake8_installation(self, work_dir):
        """Test that flake8 is available."""
        try:
            result = subprocess.run(
                ["flake8", "--version"],
                capture_output=True,
                text=True,
                timeout=10
            )
            assert result.returncode == 0, "flake8 is not properly installed"
            logger.info("flake8 is available")
        except FileNotFoundError:
            pytest.skip("flake8 not installed")

    def test_flake8_basic_usage(self, work_dir):
        """Test basic flake8 functionality."""
        # Create a simple test file
        test_file = os.path.join(work_dir, "test_flake8.py")
        with open(test_file, 'w') as f:
            f.write('''#!/usr/bin/env python3
"""
Test file for flake8 validation.
"""

def test_function():
    """Test function for flake8."""
    return "test"


if __name__ == "__main__":
    print(test_function())
''')
        
        # Run flake8 on the test file
        try:
            result = subprocess.run(
                ["flake8", test_file],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            # flake8 should run without errors
            assert result.returncode == 0, f"flake8 found issues: {result.stdout}"
            logger.info("flake8 basic functionality test passed")
            
        except subprocess.TimeoutExpired:
            pytest.fail("flake8 test timed out")
        except Exception as e:
            pytest.fail(f"flake8 test failed: {e}")

    def test_pep8_compliance(self, work_dir):
        """Test PEP 8 compliance."""
        # Create a test file with various PEP 8 issues
        test_file = os.path.join(work_dir, "pep8_test.py")
        with open(test_file, 'w') as f:
            f.write('''#!/usr/bin/env python3
"""
Test file for PEP 8 compliance.
"""

import os
import sys

# This line is too long and should trigger E501
very_long_line_that_exceeds_the_maximum_line_length_and_should_trigger_a_flake8_error = "test"

def test_function_with_bad_spacing( x,y ):
    """Function with bad spacing."""
    if x==y:
        return True
    else:
        return False

class BadClass:
    def __init__(self):
        pass
    
    def method_with_bad_indentation(self):
      return "bad indentation"

# Missing blank line at end of file
''')
        
        # Run flake8 and check for expected errors
        try:
            result = subprocess.run(
                ["flake8", test_file],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            # Should find PEP 8 violations
            assert result.returncode != 0, "flake8 should find PEP 8 violations"
            
            output = result.stdout + result.stderr
            
            # Check for specific error codes
            expected_errors = ["E501", "E201", "E202", "E225", "E111", "W292"]
            found_errors = []
            
            for error_code in expected_errors:
                if error_code in output:
                    found_errors.append(error_code)
            
            assert len(found_errors) > 0, f"No expected PEP 8 errors found. Output: {output}"
            logger.info(f"Found PEP 8 violations: {found_errors}")
            
        except subprocess.TimeoutExpired:
            pytest.fail("flake8 PEP 8 test timed out")
        except Exception as e:
            pytest.fail(f"flake8 PEP 8 test failed: {e}")

    def test_debian_specific_style_standards(self, work_dir):
        """Test Debian-specific style standards."""
        # Create a test file following Debian style standards
        test_file = os.path.join(work_dir, "debian_style_test.py")
        with open(test_file, 'w') as f:
            f.write('''#!/usr/bin/env python3
"""
Debian-specific test file for flake8 validation.
"""

import os
import subprocess
import logging
from typing import Dict, List, Any, Optional

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


class DebianBootcBuilder:
    """Debian bootc image builder class."""
    
    def __init__(self, work_dir: str):
        """Initialize the builder."""
        self.work_dir = work_dir
        self.packages: List[str] = []
        self.release = "trixie"
        self.arch = "amd64"
    
    def add_package(self, package: str) -> None:
        """Add a package to the installation list."""
        if package not in self.packages:
            self.packages.append(package)
            logger.info(f"Added package: {package}")
    
    def set_release(self, release: str) -> None:
        """Set the Debian release."""
        valid_releases = ["trixie", "bookworm", "bullseye"]
        if release in valid_releases:
            self.release = release
            logger.info(f"Set release to: {release}")
        else:
            raise ValueError(f"Invalid release: {release}")
    
    def build_image(self) -> Dict[str, Any]:
        """Build the Debian image."""
        logger.info("Starting Debian image build")
        
        # Validate configuration
        if not self.packages:
            raise ValueError("No packages specified")
        
        # Build process would go here
        result = {
            "status": "success",
            "packages": self.packages,
            "release": self.release,
            "arch": self.arch
        }
        
        logger.info("Debian image build completed")
        return result


def main() -> None:
    """Main function."""
    builder = DebianBootcBuilder("/tmp/test")
    builder.add_package("linux-image-amd64")
    builder.add_package("systemd")
    builder.set_release("trixie")
    
    try:
        result = builder.build_image()
        print(f"Build result: {result}")
    except Exception as e:
        logger.error(f"Build failed: {e}")


if __name__ == "__main__":
    main()

''')
        
        # Run flake8 on the Debian style file
        try:
            result = subprocess.run(
                ["flake8", test_file],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            # Should pass flake8 validation
            assert result.returncode == 0, f"flake8 found issues in Debian style file: {result.stdout}"
            logger.info("Debian-specific style standards test passed")
            
        except subprocess.TimeoutExpired:
            pytest.fail("flake8 Debian style test timed out")
        except Exception as e:
            pytest.fail(f"flake8 Debian style test failed: {e}")

    def test_flake8_configuration(self, work_dir):
        """Test flake8 configuration and custom rules."""
        # Create a flake8 configuration file
        setup_cfg = os.path.join(work_dir, "setup.cfg")
        with open(setup_cfg, 'w') as f:
            f.write('''[flake8]
# Maximum line length
max-line-length = 120

# Ignore specific error codes
ignore = E203, W503

# Exclude directories
exclude = .git,__pycache__,.venv

# Maximum complexity
max-complexity = 10
''')
        
        # Create a test file that would normally trigger ignored errors
        test_file = os.path.join(work_dir, "config_test.py")
        with open(test_file, 'w') as f:
            f.write('''#!/usr/bin/env python3
"""
Test file for flake8 configuration.
"""

def test_function():
    """Test function for flake8 config."""
    # This line is long but should be allowed by config
    very_long_line_that_exceeds_normal_pep8_but_is_allowed_by_our_config = "test"
    return very_long_line_that_exceeds_normal_pep8_but_is_allowed_by_our_config


if __name__ == "__main__":
    print(test_function())

''')
        
        # Run flake8 with custom configuration
        try:
            result = subprocess.run(
                ["flake8", "--config", setup_cfg, test_file],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            # Should pass with custom configuration
            assert result.returncode == 0, f"flake8 with custom config failed: {result.stdout}"
            logger.info("flake8 configuration test passed")
            
        except subprocess.TimeoutExpired:
            pytest.fail("flake8 configuration test timed out")
        except Exception as e:
            pytest.fail(f"flake8 configuration test failed: {e}")

    def test_flake8_error_codes(self, work_dir):
        """Test specific flake8 error codes."""
        # Create a test file with specific error types
        test_file = os.path.join(work_dir, "error_codes_test.py")
        with open(test_file, 'w') as f:
            f.write('''#!/usr/bin/env python3
"""
Test file for specific flake8 error codes.
"""

# E501: Line too long
very_long_line_that_exceeds_the_maximum_line_length_and_should_trigger_a_flake8_error = "test"

# E201: Whitespace after '('
def function_with_bad_spacing( x ):
    return x

# E202: Whitespace before ')'
def another_bad_function( y ):
    return y

# E225: Missing whitespace around operator
x=1
y=2
z=x+y

# E111: Bad indentation
def bad_indentation():
  return "bad"

# W292: No newline at end of file
result = "no newline"
''')
        
        # Run flake8 and check for specific error codes
        try:
            result = subprocess.run(
                ["flake8", test_file],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            # Should find errors
            assert result.returncode != 0, "flake8 should find style errors"
            
            output = result.stdout + result.stderr
            
            # Check for specific error codes
            expected_errors = ["E501", "E201", "E202", "E225", "E111", "W292"]
            found_errors = []
            
            for error_code in expected_errors:
                if error_code in output:
                    found_errors.append(error_code)
            
            # Should find at least some of the expected errors
            assert len(found_errors) >= 3, f"Expected more error codes. Found: {found_errors}"
            logger.info(f"Found flake8 error codes: {found_errors}")
            
        except subprocess.TimeoutExpired:
            pytest.fail("flake8 error codes test timed out")
        except Exception as e:
            pytest.fail(f"flake8 error codes test failed: {e}")


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