#!/usr/bin/env python3
"""Generate .pyi stub files for @configurable decorated functions and classes.

This script scans Python files for @configurable decorators on functions,
methods, classes (with __init__), and dataclasses. It generates corresponding
type stub files with TypedDict configs and ConfigurableIndicator wrappers.
"""

from __future__ import annotations

import argparse
from pathlib import Path
import sys

from loguru import logger

from hipr.stubs import process_file


def _process_python_files(src_dir: Path) -> int:
  """Process all Python files in directory and count generated stubs.

  Args:
    src_dir: Directory to scan for Python files

  Returns:
    Number of stub files generated
  """
  python_files = list(src_dir.rglob("*.py"))
  generated_count = 0

  for py_file in python_files:
    if "__pycache__" in str(py_file):
      logger.debug("Skipping cache directory: {}", py_file)
      continue

    if py_file.name.startswith("test_"):
      logger.debug("Skipping test file: {}", py_file)
      continue

    try:
      if process_file(py_file):
        generated_count += 1
    except SyntaxError as e:
      logger.error("Syntax error in {}: {}", py_file, e)
    except OSError as e:
      logger.error("I/O error reading {}: {}", py_file, e)
    except ValueError as e:
      logger.error("Invalid constraint in {}: {}", py_file, e)
    except (ImportError, AttributeError, RuntimeError) as e:
      # Specific errors that can occur during stub generation
      logger.error("Error processing {}: {}", py_file, e)

  return generated_count


def main(argv: list[str] | None = None) -> int:
  """Scan directory and generate stubs for all @configurable functions.

  Args:
    argv: Command line arguments (uses sys.argv if None)

  Returns:
    Exit code (0 for success, 1 for error)
  """
  parser = argparse.ArgumentParser(
    description="Generate .pyi stub files for @configurable decorators",
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog="""
Examples:
  # Generate stubs for src/ directory (default)
  hipr-generate-stubs

  # Generate stubs for a specific directory
  hipr-generate-stubs my_package/

  # Generate stubs for current directory
  hipr-generate-stubs .
    """,
  )
  parser.add_argument(
    "path",
    nargs="?",
    default="src",
    help="Directory to scan for @configurable decorators (default: src)",
  )
  parser.add_argument(
    "--verbose",
    "-v",
    action="store_true",
    help="Enable verbose logging",
  )

  args = parser.parse_args(argv)

  # Extract typed values from argparse Namespace
  # pyright doesn't have type stubs for argparse.Namespace dynamic attributes
  verbose: bool = bool(args.verbose)  # pyright: ignore[reportAny]
  path_str: str = str(args.path)  # pyright: ignore[reportAny]

  if not verbose:
    logger.remove()  # Remove default handler
    logger.add(sys.stderr, level="INFO", format="<level>{message}</level>")

  src_dir = Path(path_str)

  if not src_dir.exists():
    logger.error("Error: Directory '{}' not found", src_dir)
    return 1

  if not src_dir.is_dir():
    logger.error("Error: '{}' is not a directory", src_dir)
    return 1

  generated_count = _process_python_files(src_dir)
  logger.info("Generated {} stub file(s)", generated_count)
  return 0


if __name__ == "__main__":
  sys.exit(main())
