#!/usr/bin/env python3
"""
Base module system for BrowserOS build pipeline

This module defines the base class for all build modules and the validation framework.
All build modules should inherit from BuildModule and implement validate() and execute().
"""

from typing import List


class ValidationError(Exception):
    """
    Raised when module validation fails

    This exception is raised by the validate() method when a module cannot execute
    due to missing requirements, platform incompatibility, or invalid configuration.
    The build pipeline stops immediately when ValidationError is raised.
    """
    pass


class CommandModule:
    """
    Base class for all build modules

    Each module represents a discrete step in the build pipeline (e.g., clean, compile, sign).
    Modules are self-contained and declare their requirements and outputs explicitly.

    Class Attributes:
        produces: List of artifact names this module creates (e.g., ["signed_app", "notarization_zip"])
        requires: List of artifact names this module needs (e.g., ["built_app"])
        description: Human-readable description for --list output

    Methods:
        validate(context): Check if module can run, raise ValidationError if not
        execute(context): Execute the module's main task

    Example:
        class CleanModule(BuildModule):
            produces = []
            requires = []
            description = "Clean build artifacts and reset git state"

            def validate(self, context):
                if not context.chromium_src.exists():
                    raise ValidationError(f"Chromium source not found: {context.chromium_src}")

            def execute(self, context):
                log_info("🧹 Cleaning build artifacts...")
                # ... cleaning logic ...
                log_success("Build artifacts cleaned")
    """

    # Metadata as class attributes (override in subclasses)
    produces: List[str] = []
    requires: List[str] = []
    description: str = "No description provided"

    def validate(self, context) -> None:
        """
        Validate that this module can run successfully

        This method should check all preconditions:
        - Platform requirements (e.g., macOS only)
        - Required artifacts from previous modules
        - Required environment variables
        - Required files/directories exist

        Args:
            context: BuildContext object with all build state

        Raises:
            ValidationError: If any precondition is not met

        Note:
            This method is called before execute(). The pipeline stops
            immediately if ValidationError is raised.
        """
        raise NotImplementedError(
            f"{self.__class__.__name__} must implement validate()"
        )

    def execute(self, context) -> None:
        """
        Execute the module's main task

        This method performs the actual work of the module. It should:
        - Log its own progress using log_info(), log_success(), etc.
        - Register any artifacts it produces using context.artifacts.add()
        - Raise exceptions on failure (will stop the pipeline)

        Args:
            context: BuildContext object with all build state

        Raises:
            Exception: On any failure (stops the pipeline)

        Note:
            This method is only called after validate() succeeds.
            Modules should be idempotent where possible.
        """
        raise NotImplementedError(
            f"{self.__class__.__name__} must implement execute()"
        )
