"""GenTUI — Standalone TUI tool for generating and editing TactiTerm challenges with AI."""
import os
import argparse
import asyncio
import httpx

from textual.app import App, ComposeResult
from textual.screen import ModalScreen
from textual.containers import Container, Horizontal, VerticalScroll
from textual.widgets import Header, Footer, Static, Button, Markdown, TextArea, Input, Select
from textual.binding import Binding

from src.core.generator import generator
from src.core.config import config
from src.core.mentor import get_chat_completions_url


class GenHelpModal(ModalScreen):
    """Interactive AI Assistant Modal for helping user design challenges."""

    DEFAULT_CSS = """
    GenHelpModal {
        align: center middle;
        background: rgba(0, 0, 0, 0.7);
    }

    #help-dialog {
        width: 75%;
        height: 80%;
        background: $surface;
        border: thick $primary;
        padding: 1 2;
        layout: vertical;
    }

    #help-header {
        text-align: center;
        text-style: bold;
        background: $primary;
        color: white;
        height: 1;
        margin-bottom: 1;
    }

    #help-response-scroll {
        height: 1fr;
        border: solid $secondary;
        padding: 1;
        background: $background;
        margin-bottom: 1;
        overflow-y: auto;
    }

    #help-input-label {
        height: 1;
        text-style: bold;
        color: $accent;
    }

    #help-input {
        margin-bottom: 1;
    }

    #help-button-container {
        height: 3;
        layout: horizontal;
    }

    #btn-ask-help {
        width: 1fr;
        margin-right: 1;
    }

    #btn-close-help {
        width: 1fr;
    }
    """

    BINDINGS = [
        Binding("ctrl+up", "scroll_up", "Scroll Up (Ctrl+↑)"),
        Binding("ctrl+down", "scroll_down", "Scroll Down (Ctrl+↓)"),
    ]

    def action_scroll_up(self) -> None:
        self.query_one("#help-response-scroll", VerticalScroll).scroll_up(animate=False)

    def action_scroll_down(self) -> None:
        self.query_one("#help-response-scroll", VerticalScroll).scroll_down(animate=False)

    def compose(self) -> ComposeResult:

        with Container(id="help-dialog"):
            yield Static("💡 TactiTerm AI Challenge Design Assistant", id="help-header")
            with VerticalScroll(id="help-response-scroll"):
                yield Markdown(
                    "### How can I help you design your challenge?\n"
                    "Ask me anything if you're unsure about what language features, topics, requirements, or expected outputs to use!",
                    id="help-response-markdown",
                )
            yield Static("Ask Assistant a Question:", id="help-input-label")
            yield Input(
                placeholder="e.g. What are good topics for a Medium Rust challenge? Or what requirements should a Java OOP challenge have?",
                id="help-input",
            )
            with Horizontal(id="help-button-container"):
                yield Button("✨ Ask Assistant (Enter)", id="btn-ask-help", variant="warning")
                yield Button("Close Window", id="btn-close-help", variant="error")

    def on_mount(self) -> None:
        self.query_one("#help-input", Input).focus()

    def on_button_pressed(self, event: Button.Pressed) -> None:
        if event.button.id == "btn-ask-help":
            self.action_ask_assistant()
        elif event.button.id == "btn-close-help":
            self.dismiss()

    def on_input_submitted(self, event: Input.Submitted) -> None:
        if event.input.id == "help-input":
            self.action_ask_assistant()

    def action_ask_assistant(self) -> None:
        question = self.query_one("#help-input", Input).value.strip()
        if not question:
            return

        self.query_one("#help-response-markdown", Markdown).update("⏳ **Assistant is thinking...**\n\n*Consulting LLM backend for advice...*")
        self.run_worker(self._ask_worker(question))

    async def _ask_worker(self, question: str) -> None:
        endpoint = get_chat_completions_url(config.llm_base_url)
        payload = {
            "model": config.llm_model,
            "messages": [
                {
                    "role": "system",
                    "content": (
                        "You are an expert Software Engineering Curriculum Designer assisting a teacher in creating coding challenges. "
                        "Give clear, concise, actionable advice for challenge topics, difficulties, programming languages, and requirements."
                    ),
                },
                {"role": "user", "content": question},
            ],
            "max_tokens": 1000,
        }

        headers = {"Content-Type": "application/json"}
        if config.llm_api_key and config.llm_api_key != "not-needed":
            headers["Authorization"] = f"Bearer {config.llm_api_key}"

        try:
            async with httpx.AsyncClient(timeout=config.llm_timeout, follow_redirects=True) as client:
                response = await client.post(endpoint, json=payload, headers=headers)
                response.raise_for_status()
                data = response.json()
                text = (
                    data.get("choices", [{}])[0]
                    .get("message", {})
                    .get("content", "No response received.")
                )
                self.query_one("#help-response-markdown", Markdown).update(text)
        except Exception as e:
            self.query_one("#help-response-markdown", Markdown).update(f"⚠️ Error asking Assistant: {e}")


class GenTUIApp(App):
    """Standalone TUI Challenge Generator Application."""

    TITLE = "TactiTerm GenTUI"

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

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

    /* Left Panel: Generator Controls */
    #control-panel {
        width: 32%;
        min-width: 28;
        height: 100%;
        border-right: heavy $primary;
        padding: 0 1;
    }

    /* Middle Panel: Raw Markdown Editor */
    #editor-panel {
        width: 36%;
        height: 100%;
        padding: 0 1;
        border-right: heavy $primary;
    }

    /* Right Panel: Live Markdown Preview */
    #preview-panel {
        width: 32%;
        height: 100%;
        padding: 0 1;
    }

    .section-header {
        height: 3;
        background: $primary;
        color: white;
        content-align: center middle;
        text-style: bold;
        margin-bottom: 1;
    }

    .input-label {
        height: 1;
        text-style: bold;
        color: $accent;
        margin-top: 1;
    }

    Input, Select {
        margin-bottom: 1;
    }

    TextArea {
        height: 1fr;
        border: solid $accent;
        margin-bottom: 1;
    }

    #preview-scroll {
        height: 1fr;
        border: solid $secondary;
        padding: 1;
        background: $surface;
        overflow-y: auto;
    }

    #btn-help-modal {
        width: 100%;
        margin-top: 1;
        margin-bottom: 1;
    }

    #btn-generate, #btn-save {
        width: 100%;
        margin-top: 1;
        margin-bottom: 1;
    }

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

    BINDINGS = [
        Binding("ctrl+h", "open_help_modal", "AI Helper"),
        Binding("ctrl+g", "generate_ai", "Generate AI"),
        Binding("ctrl+s", "save_challenge", "Save File"),
        Binding("ctrl+q", "quit", "Quit"),
    ]

    LANGUAGES = ["Python", "C#", "C++", "Java", "JavaScript", "TypeScript", "Rust", "Lua", "HTML", "Go"]
    DIFFICULTIES = ["Easy", "Medium", "Hard", "Advanced"]

    def __init__(self, debug: bool = False) -> None:
        super().__init__()
        self.debug_mode = debug

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

        with Horizontal(id="main-container"):
            # Left Panel: Prompt Controls
            with Container(id="control-panel"):
                yield Static("1. Prompt AI Generator", classes="section-header")

                yield Button("💡 Help Me Decide (AI Assist) [Ctrl+H]", id="btn-help-modal", variant="default")

                yield Static("AI Challenge Prompt:", classes="input-label")
                yield Input(
                    placeholder="e.g. Medium Rust challenge on Ownership & References",
                    id="input-prompt",
                )

                yield Static("Language (Dropdown):", classes="input-label")
                yield Select.from_values(
                    self.LANGUAGES,
                    allow_blank=False,
                    value="Python",
                    id="select-language",
                )

                yield Static("Difficulty (Dropdown):", classes="input-label")
                yield Select.from_values(
                    self.DIFFICULTIES,
                    allow_blank=False,
                    value="Medium",
                    id="select-difficulty",
                )

                yield Static("Subject / Topic:", classes="input-label")
                yield Input(placeholder="e.g. Memory Management, Data Structures", id="input-subject", value="General Concepts")

                yield Button("✨ Generate with AI (Ctrl+G)", id="btn-generate", variant="warning")

                yield Static("Filename (.md):", classes="input-label")
                yield Input(placeholder="new-challenge.md", id="input-filename")

                yield Button("💾 Save Challenge to Disk (Ctrl+S)", id="btn-save", variant="success")

            # Middle Panel: Markdown Code Editor
            with Container(id="editor-panel"):
                yield Static("2. Raw Markdown (.md) Editor", classes="section-header")
                yield TextArea(id="markdown-editor")

            # Right Panel: Live Preview
            with Container(id="preview-panel"):
                yield Static("3. Live Rendered Preview", classes="section-header")
                with VerticalScroll(id="preview-scroll"):
                    yield Markdown("AI generated preview will appear here...", id="markdown-preview")

        yield Static("Ready — Type your prompt and click Generate with AI", id="status-bar")
        yield Footer()

    def on_mount(self) -> None:
        editor = self.query_one("#markdown-editor", TextArea)
        if "markdown" in editor.available_languages:
            editor.language = "markdown"
        self.query_one("#input-prompt", Input).focus()

    def on_button_pressed(self, event: Button.Pressed) -> None:
        if event.button.id == "btn-help-modal":
            self.action_open_help_modal()
        elif event.button.id == "btn-generate":
            self.action_generate_ai()
        elif event.button.id == "btn-save":
            self.action_save_challenge()

    def on_text_area_changed(self, event: TextArea.Changed) -> None:
        """Update live preview whenever markdown editor content changes."""
        if event.text_area.id == "markdown-editor":
            self.query_one("#markdown-preview", Markdown).update(event.text_area.text)

    def action_open_help_modal(self) -> None:
        """Pop up the AI assistant help window."""
        self.push_screen(GenHelpModal())

    def action_generate_ai(self) -> None:
        """Generate challenge markdown using LLM service worker."""
        prompt_text = self.query_one("#input-prompt", Input).value.strip()
        if not prompt_text:
            self.query_one("#status-bar", Static).update("Please enter an AI prompt description.")
            return

        lang_select = self.query_one("#select-language", Select)
        diff_select = self.query_one("#select-difficulty", Select)

        lang = str(lang_select.value) if lang_select.value != Select.BLANK else "Python"
        diff = str(diff_select.value) if diff_select.value != Select.BLANK else "Medium"
        subj = self.query_one("#input-subject", Input).value.strip() or "General"

        self.query_one("#status-bar", Static).update("⏳ Generating challenge via LLM backend...")
        self.run_worker(self._generate_worker(prompt_text, diff, lang, subj))

    async def _generate_worker(self, prompt: str, difficulty: str, language: str, subject: str) -> None:
        res = await generator.generate_challenge_async(prompt, difficulty=difficulty, language=language, subject=subject)

        if res.get("status") == "success":
            md_text = res.get("markdown", "")
            filename = res.get("filename", "new-challenge.md")

            editor = self.query_one("#markdown-editor", TextArea)
            editor.text = md_text
            self.query_one("#input-filename", Input).value = filename
            self.query_one("#markdown-preview", Markdown).update(md_text)

            self.query_one("#status-bar", Static).update(f"✓ Challenge generated: '{res.get('title')}' — Edit or click Save to disk")
        else:
            err_msg = res.get("message", "Unknown error")
            self.query_one("#status-bar", Static).update(f"✗ Challenge Generation Failed: {err_msg}")

    def action_save_challenge(self) -> None:
        """Save the markdown content to disk."""
        filename = self.query_one("#input-filename", Input).value.strip()
        md_text = self.query_one("#markdown-editor", TextArea).text.strip()

        if not filename:
            self.query_one("#status-bar", Static).update("Please specify a filename (.md) before saving.")
            return

        if not md_text:
            self.query_one("#status-bar", Static).update("Markdown editor is empty — write or generate content first.")
            return

        res = generator.save_challenge(filename, md_text)
        if res.get("status") == "success":
            self.query_one("#status-bar", Static).update(f"✓ Saved challenge file to {res.get('path')}")
        else:
            self.query_one("#status-bar", Static).update(f"✗ Save Error: {res.get('message')}")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="GenTUI — TactiTerm AI Challenge Generator")
    parser.add_argument("--debug", action="store_true", help="Enable debug logging")
    args = parser.parse_args()

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