"""
Renderer discovery and registration system.
Mirrors the PACKAGE_MANAGERS tuple pattern from adapters/package_managers/api.py
"""

from ossiq.domain.common import (
    Command,
    UnknownCommandException,
    UnknownUserInterfaceType,
    UserInterfaceType,
)
from ossiq.settings import Settings
from ossiq.ui.interfaces import AbstractUserInterfaceRenderer
from ossiq.ui.renderers.export.csv import CsvExportRenderer
from ossiq.ui.renderers.export.json import JsonExportRenderer
from ossiq.ui.renderers.package.console import ConsolePackageRenderer
from ossiq.ui.renderers.scan.console import ConsoleScanRenderer
from ossiq.ui.renderers.scan.html import HtmlScanRenderer

# Registry of all available renderers (populated via register_renderers)
# Similar to PACKAGE_MANAGERS tuple
RENDERERS: tuple[type[AbstractUserInterfaceRenderer], ...] = (
    ConsoleScanRenderer,
    HtmlScanRenderer,
    JsonExportRenderer,
    CsvExportRenderer,
    ConsolePackageRenderer,
)


def get_renderer(
    command: Command, user_interface_type: UserInterfaceType, settings: Settings
) -> AbstractUserInterfaceRenderer:
    """
    Get appropriate renderers for command and presentation type.

    Similar to create_package_managers() but returns single instance instead of iterable.

    Args:
        command: The command being executed (SCAN, EXPORT, etc.)
        user_interface_type: Desired output format (CONSOLE, HTML, etc.)
        settings: Application settings

    Returns:
        Instantiated renderer instances

    Raises:
        UnknownCommandException: No renderer found for command
        UnknownUserInterfaceType: No renderer found for presentation type

    """
    renderer_instances = [
        renderer_class(settings)
        for renderer_class in RENDERERS
        if renderer_class.supports(command, user_interface_type)
    ]

    if len(renderer_instances) > 1:
        raise TypeError(f"Only single renderer allowed for pair ({command}, {user_interface_type})")

    if renderer_instances:
        return renderer_instances[0]

    # Check if command is known (any renderer supports it)
    command_exists = any(
        renderer_class.supports(command, pt) for renderer_class in RENDERERS for pt in UserInterfaceType
    )

    if not command_exists:
        raise UnknownCommandException(f"Unknown command: {command}")

    raise UnknownUserInterfaceType(
        f"Unknown presentation type '{user_interface_type.value}' for command '{command.value}'"
    )
