"""TactiTerm TUI — Coding Tutor Terminal User Interface with W3Schools-style Handbook & Expandable Output Terminal."""
import argparse
import logging
from typing import List, Dict, Any

from textual.app import App, ComposeResult
from textual.containers import Container, Horizontal, VerticalScroll
from textual.widgets import Header, Footer, Static, OptionList, Button, Markdown, TextArea, Input
from textual.widgets.option_list import Option
from textual.binding import Binding

from src.core.loader import ChallengeLoader
from src.core.executor import executor
from src.core.linter import linter
from src.core.mentor import mentor
from src.core.handbook import handbook_service
from src.core.prompts import get_mentor_prompt
from src.tui.widgets import CodeEditor, MentorInputTextArea, StdinInput, TUI_COMPLETIONS


class TactiTermTUI(App):
    """A coding tutor TUI with direct core service integration, Mentor, Handbook, and Expandable Stdin Output Terminal."""

    TITLE = "TactiTerm"

    CSS = """
    Screen {
        layout: vertical;
    }

    #main-container {
        layout: horizontal;
        height: 1fr;
        width: 100%;
    }

    /* Left column: challenge list & details */
    #challenge-panel {
        width: 32%;
        min-width: 25;
        height: 100%;
        border-right: heavy $primary;
        padding: 0 1;
    }

    /* Middle column: code editor & execution output */
    #editor-panel {
        width: 68%;
        height: 100%;
        padding: 0 1;
    }

    /* Right columns: Mentor & Handbook sidebars (hidden by default) */
    #mentor-sidebar, #handbook-sidebar {
        width: 32%;
        min-width: 26;
        height: 100%;
        padding: 0 1;
        display: none;
    }

    /* Adjusted column widths when a sidebar is toggled open */
    #main-container.sidebar-open #challenge-panel {
        width: 26%;
    }

    #main-container.sidebar-open #editor-panel {
        width: 44%;
        border-right: heavy $primary;
    }

    #main-container.sidebar-mentor-open #mentor-sidebar {
        display: block;
        width: 30%;
    }

    #main-container.sidebar-handbook-open #handbook-sidebar {
        display: block;
        width: 30%;
    }

    #challenge-header, #mentor-header, #handbook-header {
        height: 3;
        background: $primary;
        color: white;
        content-align: center middle;
        text-style: bold;
        margin-bottom: 1;
    }

    #challenge_list {
        height: 8;
        border: solid $secondary;
        margin-bottom: 1;
    }

    #handbook-search-input {
        margin-bottom: 1;
    }

    #btn-handbook-mode {
        width: 100%;
        margin-bottom: 1;
    }

    #handbook_topic_list {
        height: 8;
        border: solid $secondary;
        margin-bottom: 1;
    }

    #challenge-details-container {
        height: 1fr;
        border: solid $primary-darken-2;
        padding: 1;
        background: $surface;
        overflow-y: auto;
    }

    /* Sleek compact action bar with reduced height */
    #action-bar {
        height: 1;
        margin-bottom: 1;
    }

    #action-bar Button {
        height: 1;
        min-width: 7;
        padding: 0 1;
        margin-right: 1;
        border: none;
    }

    /* Editor & Auto-Complete Popup Overlay styling */
    CodeEditor {
        height: 1fr;
        min-height: 8;
        border: solid $accent;
        margin-bottom: 1;
    }

    CodeEditor:focus {
        border: heavy $primary;
    }

    #completion-popup {
        display: none;
        height: 8;
        background: $surface-darken-1;
        border: heavy $warning;
        margin-bottom: 1;
        padding: 0 1;
    }

    #main-container.show-completion #completion-popup {
        display: block;
    }

    #completion-title {
        height: 1;
        text-style: bold;
        color: $warning;
    }

    #completion_list_popup {
        height: 5;
        border: solid $warning-darken-2;
    }

    /* Output Console Header & Expandable Terminal */
    #output-header-bar {
        height: 1;
        margin-bottom: 1;
    }

    #output-title {
        height: 1;
        text-style: bold;
        color: $accent;
        width: 1fr;
    }

    #btn-expand-output {
        height: 1;
        min-width: 16;
        padding: 0 1;
        border: none;
    }

    #output-scroll-container {
        height: 7;
        background: $surface;
        border: solid $accent;
        padding: 1;
        overflow-y: auto;
        margin-bottom: 1;
    }

    #editor-panel.output-expanded #output-scroll-container {
        height: 15;
    }

    #expanded-input-bar {
        display: none;
        height: 3;
        layout: horizontal;
        margin-bottom: 1;
    }

    #editor-panel.output-expanded #expanded-input-bar {
        display: block;
    }

    #program-stdin-input {
        width: 1fr;
        margin-right: 1;
    }

    #btn-send-stdin {
        width: 18;
    }

    /* Mentor & Handbook Sidebar Elements */
    #mentor-response-scroll, #handbook-example-scroll {
        height: 1fr;
        background: $surface;
        border: solid $warning-darken-1;
        padding: 1;
        margin-bottom: 1;
        overflow-y: auto;
    }

    #mentor-input-title {
        height: 1;
        text-style: bold;
        color: $warning;
    }

    #mentor-question-input {
        height: 4;
        border: solid $warning;
        margin-bottom: 1;
    }

    #btn-send-mentor {
        width: 100%;
        margin-bottom: 1;
    }

    /* Status bar */
    #status-bar {
        height: 1;
        background: $primary;
        color: white;
        padding: 0 1;
        text-style: bold;
    }
    """

    BINDINGS = [
        Binding("ctrl+r", "run_code", "Run"),
        Binding("ctrl+l", "lint_code", "Lint"),
        Binding("ctrl+e,f4", "toggle_expand_output", "Expand Output (Ctrl+E / F4)"),
        Binding("f2", "check_answer", "Check", show=False),
        Binding("f1", "toggle_mentor_sidebar", "Mentor", show=False),
        Binding("f3", "toggle_handbook_sidebar", "Handbook", show=False),
        Binding("ctrl+f", "refresh_challenges", "Refresh"),
        Binding("alt+w", "scroll_output_up", "Output Up", show=False),
        Binding("alt+s", "scroll_output_down", "Output Down", show=False),
        Binding("ctrl+up", "scroll_mentor_up", "Sidebar Up", show=False),
        Binding("ctrl+down", "scroll_mentor_down", "Sidebar Down", show=False),
        Binding("alt+up", "scroll_details_up", "Details Up", show=False),
        Binding("alt+down", "scroll_details_down", "Details Down", show=False),
        Binding("escape", "unfocus_editor", "Exit Focus"),
        Binding("f6", "toggle_panel_focus", "Switch Focus"),
        Binding("ctrl+q", "quit", "Quit"),
    ]

    def __init__(self, debug: bool = False) -> None:
        super().__init__()
        self.loader = ChallengeLoader()
        self.active_challenge_id = None
        self.challenges_dict = {}
        self.catalog_functions: List[Dict[str, str]] = []
        self.catalog_subjects: List[Dict[str, str]] = []
        self.active_handbook_mode = "all"
        self.active_completion_prefix = ""
        self.debug_mode = debug

    def compose(self) -> ComposeResult:
        yield Header()

        with Horizontal(id="main-container"):
            # Left column: Challenges & Details
            with Container(id="challenge-panel"):
                yield Static("TactiTerm Workspace", id="challenge-header")
                yield OptionList(id="challenge_list")
                with VerticalScroll(id="challenge-details-container"):
                    yield Markdown("Select a challenge from the list above to view details...", id="challenge-details")

            # Middle column: Code Editor, Completion Dropdown Popup & Expandable Output Terminal
            with Container(id="editor-panel"):
                with Horizontal(id="action-bar"):
                    yield Button("▶ Run (Ctrl+R)", id="btn-run", variant="success")
                    yield Button("🔍 Lint (Ctrl+L)", id="btn-lint", variant="primary")
                    yield Button("✅ Check (F2)", id="btn-check", variant="success")
                    yield Button("💡 Mentor (F1)", id="btn-guide", variant="warning")
                    yield Button("📖 Handbook (F3)", id="btn-handbook", variant="primary")
                    yield Button("🔄 Refresh", id="btn-refresh", variant="default")

                yield CodeEditor(id="editor")

                # Auto-Completion Dropdown Popup Overlay
                with Container(id="completion-popup"):
                    yield Static("💡 Auto-Complete Suggestions (↑/↓ to navigate, Enter/Tab to insert):", id="completion-title")
                    yield OptionList(id="completion_list_popup")

                with Horizontal(id="output-header-bar"):
                    yield Static("Output Console (Alt+W/S: Scroll)", id="output-title")
                    yield Button("⤢ Expand / Input (Ctrl+E)", id="btn-expand-output", variant="primary")

                with VerticalScroll(id="output-scroll-container"):
                    yield Static("Execution and lint output will appear here...", id="output-container")

                with Horizontal(id="expanded-input-bar"):
                    yield StdinInput(placeholder="Type stdin input here and press Enter to send to program...", id="program-stdin-input")
                    yield Button("Send Input", id="btn-send-stdin", variant="success")

            # Right column 1: Mentor Sidebar
            with Container(id="mentor-sidebar"):
                yield Static("💡 Mentor", id="mentor-header")
                with VerticalScroll(id="mentor-response-scroll"):
                    yield Markdown("Ask the mentor a question or click Check Answer...", id="mentor-response-display")

                yield Static("Ask Question (Enter: Send | Shift+Enter: Newline):", id="mentor-input-title")
                yield MentorInputTextArea(id="mentor-question-input")
                yield Button("💡 Ask Mentor (Enter)", id="btn-send-mentor", variant="warning")

            # Right column 2: W3Schools-Style Handbook Sidebar
            with Container(id="handbook-sidebar"):
                yield Static("📖 W3Schools Handbook", id="handbook-header")
                yield Input(placeholder="🔍 Search built-ins or topics...", id="handbook-search-input")
                yield Button("Filter: All Items (Click to Switch)", id="btn-handbook-mode", variant="default")
                yield OptionList(id="handbook_topic_list")
                with VerticalScroll(id="handbook-example-scroll"):
                    yield Markdown("Select a function or topic above to view W3Schools reference card...", id="handbook-example-display")

        yield Static("Ready", id="status-bar")
        yield Footer()

    # ── Events & Lifecycle ────────────────────────────────────

    def action_toggle_expand_output(self) -> None:
        """Keybinding handler for Ctrl+E and F4."""
        self.toggle_expand_output()

    def on_mount(self) -> None:
        self.call_after_refresh(self.load_challenges)

    def load_challenges(self) -> None:
        self.challenges_dict = self.loader.load_all()

        try:
            option_list = self.query_one("#challenge_list", OptionList)
            option_list.clear_options()

            for cid, challenge in sorted(self.challenges_dict.items()):
                option_list.add_option(
                    Option(f"{challenge.name} ({challenge.difficulty})", id=cid)
                )

            count = len(self.challenges_dict)
            if count > 0:
                option_list.highlighted = 0
                first_opt = option_list.get_option_at_index(0)
                self.on_option_list_option_highlighted(
                    OptionList.OptionHighlighted(option_list, first_opt, 0)
                )
                self.query_one("#status-bar", Static).update(
                    f"Loaded {count} challenges — Hovering '{first_opt.prompt}' (Hit Enter to edit)"
                )
            else:
                self.query_one("#status-bar", Static).update("No challenges found in src/challenges/.")
        except Exception as e:
            if self.debug_mode:
                print(f"DEBUG: Exception in load_challenges: {e}")

    def load_handbook_catalog(self, language: str) -> None:
        catalog = handbook_service.get_catalog(language)
        self.catalog_functions = catalog.get("functions", [])
        self.catalog_subjects = catalog.get("subjects", [])
        self.filter_handbook_list()

    def filter_handbook_list(self) -> None:
        search_term = ""
        try:
            search_input = self.query_one("#handbook-search-input", Input)
            search_term = search_input.value.strip().lower()
        except Exception:
            pass

        items: List[Dict[str, str]] = []
        if self.active_handbook_mode == "functions":
            items = [dict(t, icon="⚡") for t in self.catalog_functions]
        elif self.active_handbook_mode == "subjects":
            items = [dict(t, icon="📚") for t in self.catalog_subjects]
        else:
            items = [dict(t, icon="⚡") for t in self.catalog_functions] + [dict(t, icon="📚") for t in self.catalog_subjects]

        if search_term:
            items = [
                i for i in items
                if search_term in i["title"].lower() or search_term in i["desc"].lower()
            ]

        topic_list = self.query_one("#handbook_topic_list", OptionList)
        topic_list.clear_options()

        for item in items:
            topic_list.add_option(Option(f"{item['icon']} {item['title']}", id=item["id"]))

    def on_input_changed(self, event: Input.Changed) -> None:
        if event.input.id == "handbook-search-input":
            self.filter_handbook_list()

    def on_input_submitted(self, event: Input.Submitted) -> None:
        if event.input.id == "program-stdin-input":
            self.send_program_stdin()

    def on_button_pressed(self, event: Button.Pressed) -> None:
        button_id = event.button.id
        if button_id == "btn-run":
            self.action_run_code()
        elif button_id == "btn-lint":
            self.action_lint_code()
        elif button_id == "btn-check":
            self.action_check_answer()
        elif button_id == "btn-guide":
            self.action_toggle_mentor_sidebar()
        elif button_id == "btn-handbook":
            self.action_toggle_handbook_sidebar()
        elif button_id == "btn-handbook-mode":
            self.toggle_handbook_mode()
        elif button_id == "btn-expand-output":
            self.toggle_expand_output()
        elif button_id == "btn-send-stdin":
            self.send_program_stdin()
        elif button_id == "btn-send-mentor":
            self.submit_mentor_question()
        elif button_id == "btn-refresh":
            self.action_refresh_challenges()

    def toggle_expand_output(self) -> None:
        """Toggle output terminal expansion and stdin input bar."""
        panel = self.query_one("#editor-panel")
        btn = self.query_one("#btn-expand-output", Button)
        if panel.has_class("output-expanded"):
            panel.remove_class("output-expanded")
            btn.label = "⤢ Expand / Input (Ctrl+E)"
            self.query_one("#editor", CodeEditor).focus()
            self.query_one("#status-bar", Static).update("Output console collapsed.")
        else:
            panel.add_class("output-expanded")
            btn.label = "⤡ Collapse (Ctrl+E)"
            self.query_one("#program-stdin-input", StdinInput).focus()
            self.query_one("#status-bar", Static).update(
                "Output console expanded. Type stdin input below and hit Enter to run program with input."
            )

    def send_program_stdin(self) -> None:
        """Send input text from #program-stdin-input to running code."""
        stdin_input = self.query_one("#program-stdin-input", StdinInput)
        user_stdin = stdin_input.value
        stdin_input.value = ""
        self.action_run_code(stdin=user_stdin)

    def toggle_handbook_mode(self) -> None:
        if self.active_handbook_mode == "all":
            self.active_handbook_mode = "functions"
            label = "Filter: ⚡ Built-in Functions"
        elif self.active_handbook_mode == "functions":
            self.active_handbook_mode = "subjects"
            label = "Filter: 📚 Broad Subjects"
        else:
            self.active_handbook_mode = "all"
            label = "Filter: All Items"

        self.query_one("#btn-handbook-mode", Button).label = label
        self.filter_handbook_list()

    # ── Sidebar & Focus Management ───────────────────────────

    def action_toggle_mentor_sidebar(self) -> None:
        main_box = self.query_one("#main-container")
        q_input = self.query_one("#mentor-question-input", MentorInputTextArea)

        if main_box.has_class("sidebar-mentor-open"):
            main_box.remove_class("sidebar-mentor-open")
            main_box.remove_class("sidebar-open")
            self.query_one("#editor", CodeEditor).focus()
            self.query_one("#status-bar", Static).update("Mentor sidebar closed.")
        else:
            main_box.remove_class("sidebar-handbook-open")
            main_box.add_class("sidebar-open")
            main_box.add_class("sidebar-mentor-open")
            q_input.focus()
            self.query_one("#status-bar", Static).update("Mentor sidebar open.")

    def action_toggle_handbook_sidebar(self) -> None:
        main_box = self.query_one("#main-container")

        if main_box.has_class("sidebar-handbook-open"):
            main_box.remove_class("sidebar-handbook-open")
            main_box.remove_class("sidebar-open")
            self.query_one("#editor", CodeEditor).focus()
            self.query_one("#status-bar", Static).update("Handbook sidebar closed.")
        else:
            main_box.remove_class("sidebar-mentor-open")
            main_box.add_class("sidebar-open")
            main_box.add_class("sidebar-handbook-open")

            challenge = self.challenges_dict.get(self.active_challenge_id) if self.active_challenge_id else None
            lang = challenge.language if challenge else "Python"
            self.load_handbook_catalog(lang)

            self.query_one("#handbook_topic_list", OptionList).focus()
            self.query_one("#status-bar", Static).update(f"W3Schools Handbook open for {lang}.")

    def on_mentor_input_text_area_submit_question(
        self, event: MentorInputTextArea.SubmitQuestion
    ) -> None:
        self.submit_mentor_question(event.question)

    def submit_mentor_question(self, question: str | None = None) -> None:
        if not self.active_challenge_id:
            self.query_one("#status-bar", Static).update("Please select a challenge first.")
            return

        challenge = self.challenges_dict.get(self.active_challenge_id)
        if not challenge:
            return

        q_input = self.query_one("#mentor-question-input", MentorInputTextArea)
        user_question = q_input.text.strip() if question is None else question.strip()
        code = self.query_one("#editor", CodeEditor).text

        main_box = self.query_one("#main-container")
        main_box.remove_class("sidebar-handbook-open")
        main_box.add_class("sidebar-open")
        main_box.add_class("sidebar-mentor-open")

        q_input.text = ""
        self.query_one("#mentor-response-display", Markdown).update(
            "⏳ **Mentor is thinking and generating guidance...**\n\n*Analyzing your code, task requirements, and question...*"
        )
        self.query_one("#status-bar", Static).update(
            f"⏳ Consulting Mentor at {mentor.config.llm_base_url}..."
        )
        self.run_worker(self._mentor_worker(challenge, code, user_question))

    def action_check_answer(self) -> None:
        if not self.active_challenge_id:
            self.query_one("#status-bar", Static).update("Please select a challenge first.")
            return

        challenge = self.challenges_dict.get(self.active_challenge_id)
        if not challenge:
            return

        code = self.query_one("#editor", CodeEditor).text
        if not code.strip():
            self.query_one("#status-bar", Static).update("Editor is empty — write code before checking answer.")
            return

        main_box = self.query_one("#main-container")
        main_box.remove_class("sidebar-handbook-open")
        main_box.add_class("sidebar-open")
        main_box.add_class("sidebar-mentor-open")

        check_question = (
            "Please evaluate my code implementation against all the requirements of this challenge. "
            "Check if my solution is complete and correct, point out any missing requirements or edge cases, "
            "and give me feedback on my answer."
        )

        self.query_one("#mentor-response-display", Markdown).update(
            "⏳ **Mentor is evaluating your solution against challenge requirements...**\n\n*Checking logic, requirements, and edge cases...*"
        )
        self.query_one("#status-bar", Static).update("⏳ Consulting Mentor to check answer...")
        self.run_worker(self._mentor_worker(challenge, code, check_question))

    def action_unfocus_editor(self) -> None:
        main_box = self.query_one("#main-container")
        if main_box.has_class("show-completion"):
            main_box.remove_class("show-completion")
            self.query_one("#editor", CodeEditor).focus()
            return

        self.query_one("#challenge_list", OptionList).focus()
        self.query_one("#status-bar", Static).update("Focus moved to Challenge List.")

    def action_toggle_panel_focus(self) -> None:
        focused = self.focused
        if focused and getattr(focused, "id", None) == "editor":
            main_box = self.query_one("#main-container")
            if main_box.has_class("sidebar-handbook-open"):
                self.query_one("#handbook_topic_list", OptionList).focus()
            else:
                if not main_box.has_class("sidebar-mentor-open"):
                    main_box.add_class("sidebar-open")
                    main_box.add_class("sidebar-mentor-open")
                self.query_one("#mentor-question-input", MentorInputTextArea).focus()
        elif focused and getattr(focused, "id", None) in ("mentor-question-input", "handbook_topic_list"):
            self.query_one("#challenge_list", OptionList).focus()
        else:
            self.query_one("#editor", CodeEditor).focus()

    # ── Challenge selection & Handbook selection ─────────────

    def _display_challenge(self, cid: str) -> None:
        self.active_challenge_id = cid
        challenge = self.challenges_dict.get(cid)
        if not challenge:
            return

        req_str = "\n".join(f"- {r}" for r in challenge.requirements) if challenge.requirements else "*None*"
        hint_str = "\n".join(f"- {h}" for h in challenge.hints) if challenge.hints else "*None*"

        markdown_content = f"""# {challenge.name}
**Difficulty:** {challenge.difficulty} | **Language:** {challenge.language} | **Subject:** {challenge.subject}

## Description
{challenge.description}

## Requirements
{req_str}

## Hints
{hint_str}
"""
        self.query_one("#challenge-details", Markdown).update(markdown_content)

        editor = self.query_one("#editor", CodeEditor)
        lang_key = challenge.language.lower()
        try:
            if lang_key in editor.available_languages:
                editor.language = lang_key
            else:
                editor.language = None
        except Exception:
            editor.language = None

        main_box = self.query_one("#main-container")
        if main_box.has_class("sidebar-handbook-open"):
            self.load_handbook_catalog(challenge.language)

    def on_option_list_option_highlighted(
        self, event: OptionList.OptionHighlighted
    ) -> None:
        if event.option_list.id == "challenge_list":
            selected_option = event.option
            if selected_option and selected_option.id:
                self._display_challenge(selected_option.id)
                self.query_one("#status-bar", Static).update(
                    f"Hovering Challenge: {selected_option.prompt} — Hit Enter to jump to Editor"
                )

    def on_option_list_option_selected(
        self, event: OptionList.OptionSelected
    ) -> None:
        if event.option_list.id == "challenge_list":
            selected_option = event.option
            if selected_option and selected_option.id:
                self._display_challenge(selected_option.id)
            self.query_one("#editor", CodeEditor).focus()
            self.query_one("#status-bar", Static).update("Focused: Code Editor")
        elif event.option_list.id == "completion_list_popup":
            selected_option = event.option
            if selected_option and selected_option.prompt:
                chosen_text = str(selected_option.prompt)
                editor = self.query_one("#editor", CodeEditor)
                cursor_row, cursor_col = editor.cursor_location
                suffix_len = len(self.active_completion_prefix)
                start_col = max(0, cursor_col - suffix_len)
                editor.delete((cursor_row, start_col), (cursor_row, cursor_col))
                editor.insert(chosen_text)

                main_box = self.query_one("#main-container")
                main_box.remove_class("show-completion")
                editor.focus()
                self.query_one("#status-bar", Static).update(f"✓ Inserted '{chosen_text}'")
        elif event.option_list.id == "handbook_topic_list":
            selected_option = event.option
            if selected_option and selected_option.id:
                all_items = self.catalog_functions + self.catalog_subjects
                item = next((i for i in all_items if i["id"] == selected_option.id), None)
                if item:
                    challenge = self.challenges_dict.get(self.active_challenge_id) if self.active_challenge_id else None
                    lang = challenge.language if challenge else "Python"

                    self.query_one("#handbook-example-display", Markdown).update(
                        f"⏳ **Generating W3Schools reference card for '{item['title']}' in {lang}...**"
                    )
                    self.run_worker(self._handbook_worker(lang, item["id"], item["title"]))

    def show_completion_popup(self, prefix: str, matches: List[str]) -> None:
        self.active_completion_prefix = prefix
        popup_list = self.query_one("#completion_list_popup", OptionList)
        popup_list.clear_options()

        for match in matches:
            popup_list.add_option(Option(match, id=match))

        main_box = self.query_one("#main-container")
        main_box.add_class("show-completion")
        popup_list.focus()
        if len(matches) > 0:
            popup_list.highlighted = 0

    # ── Scrolling Actions ────────────────────────────────────

    def action_scroll_mentor_up(self) -> None:
        main_box = self.query_one("#main-container")
        if main_box.has_class("sidebar-handbook-open"):
            self.query_one("#handbook-example-scroll", VerticalScroll).scroll_up(animate=False)
        else:
            self.query_one("#mentor-response-scroll", VerticalScroll).scroll_up(animate=False)

    def action_scroll_mentor_down(self) -> None:
        main_box = self.query_one("#main-container")
        if main_box.has_class("sidebar-handbook-open"):
            self.query_one("#handbook-example-scroll", VerticalScroll).scroll_down(animate=False)
        else:
            self.query_one("#mentor-response-scroll", VerticalScroll).scroll_down(animate=False)

    def action_scroll_output_up(self) -> None:
        self.query_one("#output-scroll-container", VerticalScroll).scroll_up(animate=False)

    def action_scroll_output_down(self) -> None:
        self.query_one("#output-scroll-container", VerticalScroll).scroll_down(animate=False)

    def action_scroll_details_up(self) -> None:
        self.query_one("#challenge-details-container", VerticalScroll).scroll_up(animate=False)

    def action_scroll_details_down(self) -> None:
        self.query_one("#challenge-details-container", VerticalScroll).scroll_down(animate=False)

    # ── Core Workers ─────────────────────────────────────────

    def action_refresh_challenges(self) -> None:
        self.query_one("#status-bar", Static).update("Refreshing challenges...")
        self.load_challenges()

    async def _mentor_worker(self, challenge: object, code: str, user_question: str) -> None:
        res = await mentor.get_guidance_async(challenge, code, user_question=user_question)
        response_text = res.get("mentor_response", "No response received.")

        q_header = f"### Question / Evaluation:\n> {user_question}\n\n---\n\n" if user_question else ""
        full_md = f"{q_header}{response_text}"

        self.query_one("#mentor-response-display", Markdown).update(full_md)
        self.query_one("#status-bar", Static).update("Mentor response received — Press F1 to ask or F2 to check answer")

    async def _handbook_worker(self, language: str, topic_id: str, topic_title: str) -> None:
        res = await handbook_service.generate_example_async(language, topic_id, topic_title)
        if res.get("status") == "success":
            md_text = res.get("example_markdown", "No reference card generated.")
            self.query_one("#handbook-example-display", Markdown).update(md_text)
            self.query_one("#status-bar", Static).update(f"✓ Reference card loaded for '{topic_title}'")
        else:
            err_msg = res.get("message", "Error generating reference card.")
            self.query_one("#handbook-example-display", Markdown).update(err_msg)
            self.query_one("#status-bar", Static).update("✗ Failed to generate reference card")

    def action_lint_code(self) -> None:
        code = self.query_one("#editor", CodeEditor).text
        if not code.strip():
            self.query_one("#status-bar", Static).update("Editor is empty — nothing to lint.")
            return

        self.query_one("#status-bar", Static).update("Running syntax & style lint...")
        challenge = self.challenges_dict.get(self.active_challenge_id)
        lang = challenge.language.lower() if challenge else "python"

        res = linter.lint(lang, code)
        output_widget = self.query_one("#output-container", Static)

        if res.get("exit_code") == 0:
            output_widget.update("✓ Syntax & Style clean! No linting errors detected.")
        else:
            raw = (res.get("stdout") or "") + "\n" + (res.get("stderr") or "")
            lines = [line.strip() for line in raw.strip().splitlines() if line.strip()]
            cleaned = []
            for line in lines:
                if ":" in line:
                    parts = line.split(":", 3)
                    if len(parts) >= 3 and parts[1].isdigit():
                        cleaned.append(f"Line {parts[1]}, Col {parts[2]}:{parts[3]}")
                    else:
                        cleaned.append(line)
                else:
                    cleaned.append(line)
            msg = "\n".join(cleaned) if cleaned else "Syntax error detected."
            output_widget.update(f"✗ Lint Error(s):\n{msg}")

        self.query_one("#status-bar", Static).update("Lint complete")

    def action_run_code(self, stdin: str = "") -> None:
        code = self.query_one("#editor", CodeEditor).text
        if not code.strip():
            self.query_one("#status-bar", Static).update("Editor is empty — write code before running.")
            return

        self.query_one("#status-bar", Static).update("Executing code...")
        challenge = self.challenges_dict.get(self.active_challenge_id)
        lang = challenge.language.lower() if challenge else "python"

        res = executor.run(lang, code, stdin=stdin)
        output_widget = self.query_one("#output-container", Static)

        if res.get("exit_code") == 0:
            stdout = res.get("stdout", "").strip()
            if stdout:
                output_widget.update(f"Output:\n{stdout}")
            else:
                output_widget.update("✓ Code executed successfully (exit code 0, no stdout).")
        else:
            stderr = res.get("stderr", "").strip()
            stdout = res.get("stdout", "").strip()
            err_msg = stderr or stdout or "Unknown runtime error"
            output_widget.update(f"✗ Runtime Error (exit code {res.get('exit_code')}):\n{err_msg}")

        self.query_one("#status-bar", Static).update("Run complete")


TactTermTUI = TactiTermTUI


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="TactiTerm TUI")
    parser.add_argument("--debug", action="store_true", help="Enable debug logging to tactiterm_tui.log")
    args = parser.parse_args()

    app = TactiTermTUI(debug=args.debug)
    app.run()
