"""acl chat — интерактивный AI-агент с ACL инструментами."""

from __future__ import annotations

import json as _json
from typing import Any

import typer

from acl_cli import client, config
from acl_cli.output import console, error, info, warning


# ── Tool definitions (7 ACL primitives) — OpenAI function calling format ──

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "session_create",
            "description": "Создать новую браузерную сессию. Вызывай первым делом, если session_id ещё неизвестен.",
            "parameters": {
                "type": "object",
                "properties": {
                    "user_id": {"type": "string", "description": "ID пользователя"},
                    "site_url": {"type": "string", "description": "URL сайта"},
                },
                "required": ["user_id", "site_url"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "browser_navigate",
            "description": "Открыть URL в браузерной сессии.",
            "parameters": {
                "type": "object",
                "properties": {
                    "session_id": {"type": "string"},
                    "url": {"type": "string"},
                    "wait_for": {
                        "type": "string",
                        "description": "Стратегия ожидания: networkidle, load, domcontentloaded",
                    },
                },
                "required": ["session_id", "url"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "browser_extract",
            "description": "Извлечь данные со страницы по CSS-селектору.",
            "parameters": {
                "type": "object",
                "properties": {
                    "session_id": {"type": "string"},
                    "selector": {"type": "string", "description": "CSS-селектор"},
                    "fields": {
                        "type": "object",
                        "description": "Маппинг имя_поля → CSS-селектор внутри элемента",
                    },
                    "limit": {"type": "integer"},
                },
                "required": ["session_id", "selector"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "browser_fill",
            "description": "Заполнить поля формы на странице.",
            "parameters": {
                "type": "object",
                "properties": {
                    "session_id": {"type": "string"},
                    "fields": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "selector": {"type": "string"},
                                "value": {"type": "string"},
                                "type": {"type": "string"},
                            },
                            "required": ["selector", "value"],
                        },
                        "description": "Список полей для заполнения",
                    },
                },
                "required": ["session_id", "fields"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "browser_click",
            "description": "Кликнуть по элементу на странице.",
            "parameters": {
                "type": "object",
                "properties": {
                    "session_id": {"type": "string"},
                    "selector": {"type": "string", "description": "CSS-селектор элемента"},
                    "wait_after": {"type": "string", "description": "Стратегия ожидания после клика"},
                    "wait_for_selector": {"type": "string", "description": "Селектор для ожидания после клика"},
                },
                "required": ["session_id", "selector"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "browser_authenticate",
            "description": "Авторизоваться на сайте (login_password или qr).",
            "parameters": {
                "type": "object",
                "properties": {
                    "session_id": {"type": "string"},
                    "site_url": {"type": "string"},
                    "auth_type": {"type": "string"},
                    "user_id": {"type": "string"},
                },
                "required": ["session_id", "site_url", "user_id"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "browser_screenshot",
            "description": "Сделать скриншот текущей страницы.",
            "parameters": {
                "type": "object",
                "properties": {
                    "session_id": {"type": "string"},
                },
                "required": ["session_id"],
            },
        },
    },
]

# ── Tool → API endpoint mapping ─────────────────────────────────────────

TOOL_ENDPOINTS: dict[str, str] = {
    "session_create": "/sessions",
    "browser_navigate": "/browser/navigate",
    "browser_extract": "/browser/extract",
    "browser_fill": "/browser/fill",
    "browser_click": "/browser/click",
    "browser_authenticate": "/browser/authenticate",
    "browser_screenshot": "/browser/screenshot",
}


def _get_openai_key() -> str:
    """Return OPENAI_API_KEY from env or config."""
    import os

    key = os.environ.get("OPENAI_API_KEY") or config.get("openai_api_key")
    if not key:
        error(
            "OPENAI_API_KEY не найден.\n"
            "  export OPENAI_API_KEY=sk-proj-...\n"
            "  или добавьте openai_api_key в ~/.acl/config.json"
        )
        raise typer.Exit(1)
    return key


def _execute_tool(tool_name: str, tool_input: dict[str, Any], user: str) -> dict:
    """Call the ACL API endpoint corresponding to the tool."""
    endpoint = TOOL_ENDPOINTS.get(tool_name)
    if not endpoint:
        return {"error": f"Unknown tool: {tool_name}"}

    headers = {"X-User-ID": user}

    if tool_name == "session_create":
        payload = {"user_id": tool_input.get("user_id", user), "site_url": tool_input["site_url"]}
    else:
        payload = dict(tool_input)

    try:
        result = client.post(endpoint, json=payload, headers=headers)
        return result
    except SystemExit:
        return {"error": f"API call failed for {tool_name}"}
    except Exception as exc:
        return {"error": str(exc)}


def _short_params(params: dict) -> str:
    """Format tool params for display (abbreviated)."""
    parts = []
    for k, v in params.items():
        sv = str(v)
        if len(sv) > 50:
            sv = sv[:47] + "..."
        parts.append(f"{k}={sv}")
    return ", ".join(parts)


MODEL = "gpt-4o-mini"

SYSTEM_PROMPT = """\
Ты AI-агент который управляет браузером через ACL.
Текущий пользователь: {user}
Продакшн URL: https://acl-production.up.railway.app

Для выполнения задач используй браузерные инструменты ACL.
После каждого действия кратко сообщай что сделал.
Если нужны учётные данные — попроси пользователя их сохранить через:
acl credentials save <site> <login> <password>
"""


def chat(
    user: str = typer.Option("default", "--user", "-u", help="User ID"),
) -> None:
    """Интерактивный AI-агент. Описывай задачи на естественном языке."""
    try:
        from openai import OpenAI
    except ImportError:
        error("Пакет openai не установлен: pip install openai")
        raise typer.Exit(1)

    # Validate keys
    config.require_api_key()  # ACL API key
    openai_key = _get_openai_key()

    llm = OpenAI(api_key=openai_key)
    system = SYSTEM_PROMPT.format(user=user)

    console.print()
    console.print(
        f"[bold cyan]ACL Chat[/bold cyan] ([dim]{MODEL}[/dim]) "
        f"| user: [green]{user}[/green] | [dim]Ctrl+C для выхода[/dim]"
    )
    info("Опишите задачу на естественном языке:")
    console.print()

    messages: list[dict] = [{"role": "system", "content": system}]

    try:
        while True:
            try:
                user_input = input("\u2192 ")
            except EOFError:
                break
            if not user_input.strip():
                continue

            messages.append({"role": "user", "content": user_input})

            # Conversation loop — handle tool calls
            while True:
                response = llm.chat.completions.create(
                    model=MODEL,
                    messages=messages,
                    tools=TOOLS,
                    max_tokens=4096,
                )

                choice = response.choices[0]
                msg = choice.message
                messages.append(msg)

                # Handle tool calls
                if msg.tool_calls:
                    for tc in msg.tool_calls:
                        tool_input = _json.loads(tc.function.arguments)
                        console.print(
                            f"  [yellow]\U0001f527 {tc.function.name}[/yellow]"
                            f"[dim]({_short_params(tool_input)})[/dim]"
                        )
                        result = _execute_tool(tc.function.name, tool_input, user)
                        truncated = _json.dumps(result, ensure_ascii=False, default=str)[:200]
                        console.print(f"  [dim]\u2192 {truncated}[/dim]")
                        messages.append({
                            "role": "tool",
                            "tool_call_id": tc.id,
                            "content": _json.dumps(result, ensure_ascii=False, default=str),
                        })
                    continue

                # Display text response
                if msg.content:
                    from rich.markdown import Markdown

                    console.print(Markdown(msg.content))

                break

            console.print()

    except KeyboardInterrupt:
        console.print("\n[dim]Выход из чата.[/dim]")
