#!/usr/bin/env python
import os
import sys
import shutil
from setuptools import setup, Extension
from Cython.Build import cythonize


def build_extensions(target_dirs):
    """
    Compiles all .py files in the target directories (recursively) into .so/.pyd extensions.
    Args:
        target_dirs (list or str): List of directories or single directory path to scan.
    """
    # Ensure input is a list
    if isinstance(target_dirs, str):
        target_dirs = [target_dirs]

    extensions = []
    project_root = os.getcwd()

    print(f"Scanning directories: {target_dirs}")

    for target_dir in target_dirs:
        # Ensure target directory exists
        if not os.path.exists(target_dir):
            print(f"Warning: Directory '{target_dir}' not found. Skipping.")
            continue

        # Get the absolute path of the target directory
        abs_target_dir = os.path.abspath(target_dir)

        print(f"Scanning {abs_target_dir} for Python files...")

        # Walk through the directory
        for root, dirs, files in os.walk(abs_target_dir):
            for file in files:
                if file.endswith(".py"):
                    file_path = os.path.join(root, file)

                    # Skip this script if it happens to be in the target dir
                    if os.path.abspath(file_path) == os.path.abspath(__file__):
                        continue

                    # Skip setup.py if it exists
                    if file == "setup.py":
                        continue

                    # Determine the module name based on path relative to project root
                    # This ensures imports like 'from app.services import ...' work
                    try:
                        rel_path = os.path.relpath(file_path, project_root)
                    except ValueError:
                        # If file is not under project root, we can't easily determine module name
                        # relative to project root. Skip or warn.
                        print(
                            f"Skipping {file_path}: cannot determine relative path to {project_root}"
                        )
                        continue

                    # Convert file path to module name (e.g. app/services/foo.py -> app.services.foo)
                    module_name = os.path.splitext(rel_path)[0].replace(os.sep, ".")

                    print(f"Found: {rel_path} -> {module_name}")

                    extensions.append(Extension(module_name, [file_path]))

    if not extensions:
        print("No Python files found to compile.")
        return

    print(f"\nCompiling {len(extensions)} modules...")

    # Build options
    # compiler_directives: language_level=3 for Python 3
    # force=True: force recompilation even if timestamps are up to date
    try:
        setup(
            ext_modules=cythonize(
                extensions,
                compiler_directives={"language_level": "3"},
                build_dir="build",  # Put intermediate files in build/ directory
                force=True,
            ),
            script_args=["build_ext", "--inplace"],
        )
        print("\nCompilation successful!")
    except Exception as e:
        print(f"\nCompilation failed: {e}")
        sys.exit(1)
    finally:
        # Cleanup build directory (intermediate C files)
        if os.path.exists("build"):
            print("Cleaning up build artifacts...")
            try:
                shutil.rmtree("build")
            except OSError as e:
                print(f"Warning: Failed to clean up build directory: {e}")


if __name__ == "__main__":
    # Default directories to compile if none provided
    DEFAULT_TARGETS = ["app/services", "app/native", "app/services"]

    # Check for help flag
    if len(sys.argv) > 1 and sys.argv[1] in ["--help", "-h"]:
        print("Usage: python scripts/build_extensions.py [directory1] [directory2] ...")
        print(
            "Compiles all Python files in the given directories into C extensions (.so/.pyd)."
        )
        print(f"Default directories if none provided: {DEFAULT_TARGETS}")
        sys.exit(0)

    if len(sys.argv) > 1:
        target_directories = sys.argv[1:]
    else:
        print(f"No directories specified. Using defaults: {DEFAULT_TARGETS}")
        target_directories = DEFAULT_TARGETS

    build_extensions(target_directories)
