"""Build a Pipeline from Settings. This is the single place that knows which
concrete class each config name maps to, so adding a backend = one line here."""

from __future__ import annotations

from .config import Settings
from .monitor import Monitor
from .pipeline import Pipeline


def build(settings: Settings, monitor: Monitor | None = None) -> Pipeline:
    pipe = Pipeline(
        source=_source(settings),
        vision=_vision(settings),
        brain=_brain(settings),
        stt=_stt(settings),
        tts=_tts(settings),
        text_channel=_text(settings),
        monitor=monitor,
    )
    if monitor is not None:
        monitor.set_components(
            {
                "source": settings.source or "none",
                "vision": settings.vision or "none",
                "stt": settings.stt or "none",
                "brain": settings.brain,
                "tts": settings.tts or "none",
                "text": settings.text or "none",
            }
        )
    return pipe


def _source(s: Settings):
    if s.source in (None, "none"):
        return None
    if s.source == "mss":
        from .backends.capture_mss import MSSFrameSource

        return MSSFrameSource(interval=s.capture_interval)
    from .backends.mock import MockFrameSource

    return MockFrameSource(interval=s.capture_interval)


def _vision(s: Settings):
    if s.vision in (None, "none"):
        return None
    if s.vision == "claude":
        from .backends.claude import ClaudeVision

        return ClaudeVision(model=s.anthropic_model)
    from .backends.mock import MockVision

    return MockVision()


def _brain(s: Settings):
    if s.brain == "claude":
        from .backends.claude import ClaudeBrain

        return ClaudeBrain(model=s.anthropic_model)
    from .backends.mock import MockBrain

    return MockBrain()


def _stt(s: Settings):
    if s.stt in (None, "none"):
        return None
    if s.stt == "whisper":
        from .backends.whisper import WhisperSTT

        return WhisperSTT()
    from .backends.mock import MockSTT

    return MockSTT()


def _tts(s: Settings):
    if s.tts in (None, "none"):
        return None
    if s.tts == "melo":
        from .backends.melo import MeloTTS

        return MeloTTS()
    from .backends.mock import MockTTS

    return MockTTS()


def _text(s: Settings):
    if s.text in (None, "none"):
        return None
    raise NotImplementedError("discord text channel backend not implemented yet")
