from textual.app import App
from textual import on
from textual.containers import Horizontal, Vertical, VerticalScroll
from textual.message import Message
from textual.reactive import reactive
from textual.screen import ModalScreen
from textual.widget import Widget
from textual.widgets import Static, Input, Label, Select, Checkbox, Button
from textual.app import ComposeResult
from logging import Handler, LogRecord
from typing_extensions import override


class AmplitudeGraph(Widget):
    """Displays a simple bar graph of audio amplitude."""
    amplitude = reactive(0.0)  # 0.0 → 1.0

    def render(self) -> str:
        bar_width = max(1, self.size.width - 4)
        scaled = self.amplitude * 3
        clamped = min(scaled, 1.0)
        filled = int(clamped * bar_width)
        empty = bar_width - filled

        bar = "█" * filled + " " * empty
        return f"[{bar}] {self.amplitude:.2f}"


class SessionDisplay(Static):
    """A widget that shows the current session ID."""

    session_id = reactive("")

    @override
    def render(self) -> str:
        return f"Session ID: {self.session_id}" if self.session_id else "Connecting..."


class AudioStatusIndicator(Static):
    """A widget that shows the current audio recording status."""

    is_recording = reactive(False)

    @override
    def render(self) -> str:
        status = (
            "🔴 Recording... (Press K to stop)" if self.is_recording else "⚪ Press K to start recording (Q to quit)"
        )
        return status


class TextualLogMessage(Message):
    """A message carrying log text for the UI."""

    def __init__(self, text: str) -> None:
        self.text = text
        super().__init__()


class TextualPaneLogHandler(Handler):
    """
    Logging handler that forwards log messages into the Textual app
    using message posting (thread-safe).
    """

    def __init__(self, app: App[None]):
        super().__init__()
        self.app = app

    def emit(self, record: LogRecord):
        try:
            msg = self.format(record)
            # Post message safely into Textual's event queue
            self.app.post_message(TextualLogMessage(msg))
        except Exception:
            self.handleError(record)


class ConfigModal(ModalScreen[dict]):
    """A modal screen to edit application settings."""

    def compose(self) -> ComposeResult:
        cfg = self.app.user_config

        # Sticky Header
        yield Label("Application Settings", id="config-title")

        # Scrollable Middle Section
        with VerticalScroll(id="config-body"):
            yield Label("Model Name")
            yield Input(value=cfg["model"], name="model")

            yield Label("System Prompt")
            yield Input(value=cfg["prompt"], name="prompt")

            yield Label("Mode")
            yield Select(
                [("Manual", "manual"), ("Server VAD", "server"), ("Semantic VAD", "semantic")],
                value=cfg["mode"],
                name="mode",
            )

            current_modalities = cfg.get("output_modalities", ["text", "audio"])
            yield Label("Output Modalities")
            with Horizontal(id="modalities-row"):
                yield Checkbox("Audio", value="audio" in current_modalities, name="audio", classes="modality-check")

            yield Label("Transcription Settings")
            yield Checkbox("Transcription Enabled", value=cfg["transcription_enabled"], name="transcription_enabled")
            yield Label("Transcription Model")
            yield Input(value=cfg["transcription_model"], name="transcription_model", placeholder="Model Name")
            yield Label("Transcription Language")
            yield Input(value=cfg["language"], name="language", placeholder="Language (en, fr, etc)")

            yield Label("Miscellaneous Settings")
            yield Checkbox("Play Audio", value=cfg["play_audio"], name="play_audio")
            yield Checkbox("Immediate Initialization", value=cfg["immediate_initialisation"],
                           name="immediate_initialisation")

            yield Label("Save Audio Files (value 0 or empty for no storage)")
            with Horizontal(classes="input-row"):
                with Vertical():
                    yield Label("Speech bytes multiplier")
                    yield Input(value=str(cfg["save_speech_multiplier"]), name="save_speech_multiplier", type="integer")
                with Vertical():
                    yield Label("Silence bytes multipler")
                    yield Input(value=str(cfg["save_silence_multiplier"]), name="save_silence_multiplier", type="integer")

        # Sticky Footer
        with Horizontal(id="config-buttons"):
            yield Button("Save", variant="success", id="save_config")
            yield Button("Cancel", variant="error", id="cancel_config")

    @on(Button.Pressed)
    def handle_buttons(self, event: Button.Pressed) -> None:
        if event.button.id == "save_config":
            new_settings = {}
            for control in self.query("Input, Select, Checkbox").exclude(".modality-check"):
                val = control.value

                # Special handling for our number fields
                if input_type := getattr(control, "type", None):
                    if any(input_type == number_type for number_type in ("integer", "number")):
                        try:
                            val = int(val) if val.strip() != "" else None
                        except ValueError:
                            val = None

                new_settings[control.name] = val
            selected_modalities = [
                cb.name for cb in self.query(".modality-check") if cb.value is True
            ]
            if not selected_modalities:
                selected_modalities = ["text"]
            new_settings["output_modalities"] = selected_modalities
            print(new_settings)
            self.dismiss(new_settings)
        else:
            self.dismiss()
