#!/usr/bin/env python3

import os
import json
import yaml
import subprocess
import sys
import time
from pathlib import Path

def load_package_config():
    """Load the package configuration from aur-packages.yml"""
    with open('aur-packages.yml', 'r') as f:
        config = yaml.safe_load(f)
    return config['packages']

def build_package_test(package_name):
    """Test building a package with paru and return results."""
    print(f"\n=== Testing build for package: {package_name} ===")
    
    # Build result details
    result = {
        "package": package_name,
        "success": False,
        "error": "",
        "log": ""
    }
    
    # Create a temp directory for the build
    temp_dir = f"/tmp/aur-build-test-{package_name}"
    os.makedirs(temp_dir, exist_ok=True)
    
    # Log all output for debugging
    log_output = f"=== Build test for {package_name} ===\n\n"
    
    try:
        # Try to build the package using paru -G to download it first
        log_output += "=== Downloading package with paru -G ===\n"
        download_proc = subprocess.run(
            [
                'paru', '-G', package_name,
                '--noconfirm',
                '--noprogressbar'
            ],
            cwd=temp_dir,
            capture_output=True,
            text=True,
            check=False,
            env={**os.environ, 'LANG': 'C'}  # Use C locale for consistent output
        )
        
        log_output += f"STDOUT:\n{download_proc.stdout}\n\nSTDERR:\n{download_proc.stderr}\n\n"
        
        if download_proc.returncode != 0:
            result["error"] = f"Failed to download package with exit code {download_proc.returncode}"
            log_output += f"Build failed: {result['error']}\n"
            result["log"] = log_output
            return result
        
        # Now build it with makepkg
        log_output += "=== Building package with makepkg ===\n"
        build_proc = subprocess.run(
            [
                'makepkg', '-sf', '--noconfirm'  # -sf forces rebuild and syncs dependencies
            ],
            cwd=os.path.join(temp_dir, package_name),
            capture_output=True,
            text=True,
            check=False,
            env={**os.environ, 'LANG': 'C'}
        )
        
        log_output += f"STDOUT:\n{build_proc.stdout}\n\nSTDERR:\n{build_proc.stderr}\n\n"
        
        # If that fails, try with additional flags that might help
        if build_proc.returncode != 0:
            log_output += "=== First build attempt failed, trying with additional flags ===\n"
            
            build_proc = subprocess.run(
                [
                    'makepkg', '-sf', '--noconfirm', '--skippgpcheck'
                ],
                cwd=os.path.join(temp_dir, package_name),
                capture_output=True,
                text=True,
                check=False,
                env={**os.environ, 'LANG': 'C'}
            )
            
            log_output += f"STDOUT:\n{build_proc.stdout}\n\nSTDERR:\n{build_proc.stderr}\n\n"
        
        # Check build result
        if build_proc.returncode == 0:
            result["success"] = True
            log_output += "Build successful!\n"
            print(f"✅ Package {package_name} built successfully!")
        else:
            result["success"] = False
            result["error"] = f"Build failed with exit code {build_proc.returncode}"
            
            # Look for common error patterns
            if "One or more files did not pass the validity check!" in build_proc.stderr or "One or more files did not pass the validity check!" in build_proc.stdout:
                result["error"] = "Checksum validation failed"
            elif "target not found" in build_proc.stderr or "target not found" in build_proc.stdout:
                result["error"] = "Dependency not found"
            elif "Could not find all required packages" in build_proc.stderr or "Could not find all required packages" in build_proc.stdout:
                result["error"] = "Dependency not found"
            elif "could not determine ownership" in build_proc.stderr or "could not determine ownership" in build_proc.stdout:
                result["error"] = "Clean chroot permission issue"
            elif "keyserver receive failed" in build_proc.stderr or "keyserver receive failed" in build_proc.stdout:
                result["error"] = "GPG key retrieval failed"
            elif "unknown public key" in build_proc.stderr or "unknown public key" in build_proc.stdout:
                result["error"] = "Missing GPG key"
            elif "Permission denied" in build_proc.stderr or "Permission denied" in build_proc.stdout:
                result["error"] = "Permission denied"
            elif "error: chroot" in build_proc.stderr or "error: chroot" in build_proc.stdout:
                result["error"] = "Chroot build error"
            elif "command not found" in build_proc.stderr or "command not found" in build_proc.stdout:
                result["error"] = "Missing build command"
            elif "error: failed to prepare transaction" in build_proc.stderr or "error: failed to prepare transaction" in build_proc.stdout:
                result["error"] = "Failed to prepare transaction"
            elif "exists in filesystem" in build_proc.stderr or "exists in filesystem" in build_proc.stdout:
                result["error"] = "File conflict"
            elif "conflicting dependencies" in build_proc.stderr or "conflicting dependencies" in build_proc.stdout:
                result["error"] = "Conflicting dependencies"
            
            log_output += f"Build failed: {result['error']}\n"
            print(f"❌ Package {package_name} build failed: {result['error']}")
        
    except Exception as e:
        result["success"] = False
        result["error"] = str(e)
        log_output += f"Exception occurred: {str(e)}\n"
        print(f"❌ Package {package_name} build test raised exception: {str(e)}")
    
    # Clean up temp directory to save space
    try:
        subprocess.run(['rm', '-rf', temp_dir], check=False)
    except:
        pass
    
    # Save the complete log
    result["log"] = log_output
    return result

def write_results(results):
    """Write test results to a JSON file."""
    # Create a directory for the logs
    logs_dir = Path("package_build_logs")
    logs_dir.mkdir(exist_ok=True)
    
    # Write individual log files for each package
    for result in results:
        log_file = logs_dir / f"{result['package']}_build.log"
        with open(log_file, 'w') as f:
            f.write(result["log"])
        
        # Remove the log from the result to avoid duplication
        log_entry = result.pop("log")
        
        # Add a reference to the log file
        result["log_file"] = str(log_file)
    
    # Write the summary results file
    with open('package_build_results.json', 'w') as f:
        json.dump(results, f, indent=2)
    
    print(f"\nWritten detailed logs to {logs_dir}/")
    print(f"Written summary results to package_build_results.json")

def main():
    # Get package configuration
    package_configs = load_package_config()
    
    # Get packages to test from command line or use all configured packages
    if len(sys.argv) > 1:
        packages_to_test = sys.argv[1:]
        # Check if all packages exist in config
        for pkg in packages_to_test:
            if pkg not in package_configs:
                print(f"Warning: {pkg} not found in configuration. Testing anyway.")
    else:
        packages_to_test = list(package_configs.keys())
    
    # Store all results
    all_results = []
    failed_count = 0
    
    # Test each package
    for pkg_name in packages_to_test:
        # Add a delay between package builds to avoid issues
        if all_results:  # Not the first package
            print("Waiting 5 seconds before next package build...")
            time.sleep(5)
        
        result = build_package_test(pkg_name)
        all_results.append(result)
        
        if not result["success"]:
            failed_count += 1
    
    # Write results to file
    write_results(all_results)
    
    # Print summary
    print(f"\n=== Build Test Summary ===")
    print(f"Total packages tested: {len(all_results)}")
    print(f"Successful builds: {len(all_results) - failed_count}")
    print(f"Failed builds: {failed_count}")
    
    # Set exit code based on success
    if failed_count > 0:
        print("\nSome package builds failed. Check package_build_results.json for details.")
        sys.exit(1)
    else:
        print("\nAll package builds succeeded!")
        sys.exit(0)

if __name__ == "__main__":
    main() 