"""ACLTUI — Textual TUI приложение. Точная копия архитектуры API Gateway."""

from __future__ import annotations

import re

from rich.panel import Panel
from rich.syntax import Syntax
from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical
from textual.widgets import Input, Label, RichLog

from acl_cli.tui.agent import process_with_ai


class ACLTUI(App):
    """ACL терминальный интерфейс."""

    TITLE = "ACL — Agent Control Layer"

    CSS = """
    Screen { background: #0a0f0d; }

    #sidebar {
        width: 30%;
        border-right: solid #054035;
        padding: 1;
    }
    #sidebar-title {
        color: #00e57a;
        text-style: bold;
        margin-bottom: 1;
    }
    #chat-area {
        width: 70%;
        padding: 1;
    }
    #chat-log { height: 1fr; }
    #input-bar {
        height: 3;
        border: solid #054035;
        background: #0a1a0f;
    }
    Input { background: #0a1a0f; color: #e0ffe0; }
    .tool-start { color: #ffaa00; }
    .tool-done  { color: #00e57a; }
    .user-msg   { color: #ffffff; text-style: bold; }
    .ai-msg     { color: #b0ffb0; }
    .error-msg  { color: #ff4444; }
    .password-input { -webkit-text-security: disc; }
    """

    BINDINGS = [
        ("ctrl+c", "quit",      "Выйти"),
        ("ctrl+l", "clear",     "Очистить"),
        ("ctrl+n", "new_chat",  "Новый чат"),
        ("ctrl+y", "copy_code", "Копировать код"),
        ("f1",     "help",      "Помощь"),
    ]

    def __init__(self, user_id: str, client):
        super().__init__()
        self.user_id = user_id
        self.client = client
        self.session_id = None
        self.history = []
        self.last_code_block: str | None = None
        # Credential input state
        self._cred_mode: str | None = None  # None | "login" | "password"
        self._cred_site_domain: str | None = None
        self._pending_login: str | None = None
        self._original_message: str | None = None

    def compose(self) -> ComposeResult:
        with Horizontal():
            with Vertical(id="sidebar"):
                yield Label("История", id="sidebar-title")
                yield RichLog(id="history-log", markup=True)
                yield Label("Инструменты", classes="sidebar-section")
                yield RichLog(id="tools-log", markup=True)
            with Vertical(id="chat-area"):
                yield RichLog(id="chat-log", markup=True, wrap=True)
                yield Input(placeholder="Опишите задачу...", id="input-bar")

    async def on_input_submitted(self, event: Input.Submitted):
        value = event.value.strip()
        if not value:
            return
        event.input.value = ""
        input_bar = self.query_one("#input-bar", Input)

        # ── Credential input: login ──
        if self._cred_mode == "login":
            self._pending_login = value
            self._cred_mode = "password"
            input_bar.placeholder = "Пароль (не отображается)"
            input_bar.password = True
            return

        # ── Credential input: password ──
        if self._cred_mode == "password":
            password = value
            input_bar.password = False
            input_bar.placeholder = "Опишите задачу..."
            chat_log = self.query_one("#chat-log", RichLog)

            try:
                await self.client.save_credentials(
                    user_id=self.user_id,
                    site_domain=self._cred_site_domain,
                    auth_type="login_password",
                    login=self._pending_login,
                    password=password,
                )
                chat_log.write("[green]✅ Credentials сохранены[/]")
            except Exception as exc:
                chat_log.write(f"[red]❌ Не удалось сохранить credentials: {exc}[/]")
                self._cred_mode = None
                return

            # Повторить исходное сообщение
            original = self._original_message
            self._cred_mode = None
            self._cred_site_domain = None
            self._pending_login = None
            self._original_message = None
            if original:
                await self.process_message(original)
            return

        # ── Normal message flow ──
        chat_log = self.query_one("#chat-log", RichLog)
        chat_log.write(f"[bold white]Вы:[/] {value}")
        self.history.append(value)

        history_log = self.query_one("#history-log", RichLog)
        history_log.write(f"[dim]{value[:40]}...[/]" if len(value) > 40 else f"[dim]{value}[/]")

        await self.process_message(value)

    async def process_message(self, message: str):
        chat_log = self.query_one("#chat-log", RichLog)
        tools_log = self.query_one("#tools-log", RichLog)

        chat_log.write("[dim]🤔 Думаю...[/]")

        async for event_type, event_data in process_with_ai(
            text=message,
            user_id=self.user_id,
            client=self.client,
            session_id=self.session_id,
        ):
            if event_type == "tool_start":
                tool = event_data.get("tool", "")
                params = event_data.get("params", {})
                # Анимация в sidebar
                tools_log.write(f"[yellow]⚡ {tool}[/]")
                chat_log.write(f"[yellow]🔧 {tool}({_fmt_params(params)})[/]")

            elif event_type == "tool_done":
                tool = event_data.get("tool", "")
                tools_log.write(f"[green]✓ {tool}[/]")

            elif event_type == "response":
                text = event_data.get("text", "")
                code = _extract_code_block(text)
                if code is not None:
                    self.last_code_block = code
                    lang = _extract_code_lang(text)
                    syntax = Syntax(
                        code,
                        lang,
                        theme="monokai",
                        line_numbers=False,
                        background_color="#0a1a0f",
                    )
                    panel = Panel(
                        syntax,
                        title="[green]Готовый код[/]",
                        border_style="#054035",
                    )
                    chat_log.write(panel)
                    chat_log.write("[dim]Нажми Ctrl+Y чтобы скопировать последний код[/]")
                    # Write remaining text outside the code block
                    rest = _strip_code_block(text).strip()
                    if rest:
                        chat_log.write(f"[green]ACL:[/] {rest}")
                else:
                    chat_log.write(f"[green]ACL:[/] {text}")

            elif event_type == "error":
                msg = event_data.get("message", "")
                chat_log.write(f"[red]❌ Ошибка: {msg}[/]")

            elif event_type == "need_credentials":
                site_domain = event_data.get("site_domain", "unknown")
                chat_log.write(
                    f"[bold yellow]🔐 Для сборки тула нужны credentials от {site_domain}[/]\n"
                    "Введи логин и пароль — они будут зашифрованы и сохранены."
                )
                self._cred_mode = "login"
                self._cred_site_domain = site_domain
                self._original_message = message
                input_bar = self.query_one("#input-bar", Input)
                input_bar.placeholder = f"Логин для {site_domain}"
                return  # stop processing SSE, wait for credentials

            elif event_type == "done":
                pass

    def action_clear(self):
        self.query_one("#chat-log", RichLog).clear()

    def action_new_chat(self):
        self.session_id = None
        self.query_one("#chat-log", RichLog).clear()
        self.query_one("#tools-log", RichLog).clear()
        self.query_one("#chat-log", RichLog).write("[dim]Новый чат начат[/]")

    def action_copy_code(self):
        if not self.last_code_block:
            self.query_one("#chat-log", RichLog).write("[dim]Нет кода для копирования[/]")
            return
        import pyperclip

        pyperclip.copy(self.last_code_block)
        self.query_one("#chat-log", RichLog).write("[green]✅ Скопировано в буфер[/]")

    def action_help(self):
        self.query_one("#chat-log", RichLog).write("""[bold]Горячие клавиши:[/]
  Ctrl+C — выйти
  Ctrl+L — очистить чат
  Ctrl+N — новый чат
  Ctrl+Y — скопировать последний код
  F1     — эта справка""")


def _fmt_params(params: dict) -> str:
    """Краткое отображение параметров инструмента."""
    items = []
    for k, v in list(params.items())[:2]:
        v_str = str(v)[:30] + "..." if len(str(v)) > 30 else str(v)
        items.append(f"{k}={v_str!r}")
    return ", ".join(items)


_CODE_BLOCK_RE = re.compile(r"```(\w*)\n(.*?)```", re.DOTALL)


def _extract_code_block(text: str) -> str | None:
    """Извлечь первый код из markdown блока."""
    m = _CODE_BLOCK_RE.search(text)
    return m.group(2).rstrip("\n") if m else None


def _extract_code_lang(text: str) -> str:
    """Извлечь язык из markdown блока (по умолчанию python)."""
    m = _CODE_BLOCK_RE.search(text)
    return m.group(1) or "python" if m else "python"


def _strip_code_block(text: str) -> str:
    """Убрать первый код-блок из текста."""
    return _CODE_BLOCK_RE.sub("", text, count=1)
