# -*- coding: utf-8 -*-
"""
/knowledge 命令辅助函数模块
提供分类分组列表、stats 统计、pin/archive 子命令的纯函数实现，
以及无参数时的交互式菜单（仿 /curator 风格）。
返回字符串列表或布尔值，便于 main.py 直接 click.echo 输出，也便于测试。
"""
import click
from typing import List, Optional

from ..ansi_menu import ansi_select
from ..knowledge import KnowledgeLoader
from ..knowledge.curator import KnowledgeCurator

# 类型显示顺序与中文名映射
_CATEGORY_ORDER = ["preference", "bugfix", "experience", "tool"]
_CATEGORY_LABELS = {
    "preference": "用户偏好",
    "bugfix": "Bug 修复",
    "experience": "编码经验",
    "tool": "工具经验",
}

# 交互式主菜单选项（纯文本）
_KNOWLEDGE_MENU_OPTIONS = [
    "列出全部知识",
    "查看统计",
    "搜索知识",
    "查看详情",
    "固定知识",
    "归档知识",
]


def _level_prefix(knowledge) -> str:
    """返回级别前缀 [G]/[P]。"""
    return "G" if knowledge.level == "global" else "P"


def format_knowledge_list_grouped(loader: KnowledgeLoader) -> List[str]:
    """按类型分组列出知识，返回多行字符串列表。

    分组顺序：偏好 → bug → 经验 → 工具。
    每行格式：[G/P] name: description
    """
    all_k = loader.list_all()
    if not all_k:
        return []

    # 按类型分组
    groups: dict = {}
    for k in all_k:
        cat = k.category or "experience"
        groups.setdefault(cat, []).append(k)

    lines: List[str] = []
    for cat in _CATEGORY_ORDER:
        items = groups.get(cat, [])
        if not items:
            continue
        label = _CATEGORY_LABELS.get(cat, cat)
        lines.append(f"── {label} ──")
        for k in items:
            lines.append(f"[{_level_prefix(k)}] {k.name}: {k.description}")
    return lines


def format_knowledge_stats(
    loader: KnowledgeLoader,
    curator: Optional[KnowledgeCurator] = None,
) -> List[str]:
    """生成统计信息：按类型计数 + 总数。"""
    all_k = loader.list_all()
    total = len(all_k)

    # 按类型计数
    counts: dict = {}
    level_counts = {"global": 0, "project": 0}
    for k in all_k:
        cat = k.category or "experience"
        counts[cat] = counts.get(cat, 0) + 1
        if k.level in level_counts:
            level_counts[k.level] += 1

    lines: List[str] = [f"知识库统计（共 {total} 条）"]
    lines.append("")
    lines.append("按类型：")
    for cat in _CATEGORY_ORDER:
        if cat in counts:
            label = _CATEGORY_LABELS.get(cat, cat)
            lines.append(f"  {label}: {counts[cat]}")
    lines.append("")
    lines.append("按级别：")
    lines.append(f"  全局 [G]: {level_counts['global']}")
    lines.append(f"  项目 [P]: {level_counts['project']}")
    return lines


def handle_knowledge_pin(
    curator: Optional[KnowledgeCurator], name: str
) -> str:
    """固定知识，使其免于自动过渡。返回结果消息。"""
    if not name:
        return "[错误] 缺少知识名称：/knowledge pin <name>"
    if curator is None:
        return "[错误] 知识管理者未加载"
    if curator.pin_knowledge(name):
        return f"[OK] 已固定知识: {name}"
    return f"[错误] 固定失败: {name}（未找到该知识）"


def handle_knowledge_archive(
    curator: Optional[KnowledgeCurator], name: str
) -> str:
    """手动归档知识。返回结果消息。"""
    if not name:
        return "[错误] 缺少知识名称：/knowledge archive <name>"
    if curator is None:
        return "[错误] 知识管理者未加载"
    if curator.archive_knowledge(name):
        return f"[OK] 已归档知识: {name}"
    return f"[错误] 归档失败: {name}（未找到该知识）"


def _build_secondary_options(loader: KnowledgeLoader) -> List[str]:
    """构造二级菜单选项：[G/P] name: description。"""
    return [
        f"[{_level_prefix(k)}] {k.name}: {k.description}"
        for k in loader.list_all()
    ]


def _parse_name_from_option(option: str) -> str:
    """从二级菜单选项解析知识名。格式：'[P] name: desc' → 'name'。"""
    # 去掉 '[X] ' 前缀，再按 ': ' 分割取第一段
    if "]" in option:
        option = option.split("]", 1)[1].strip()
    if ": " in option:
        return option.split(": ", 1)[0].strip()
    return option.strip()


def handle_knowledge_interactive(
    loader: KnowledgeLoader,
    curator: Optional[KnowledgeCurator],
) -> bool:
    """交互式 /knowledge 菜单。返回 True 表示已处理。

    主菜单 6 项动作；选中需目标的动作再弹二级菜单选知识名；
    Esc 取消不报错。
    """
    choice = ansi_select(
        "知识库管理 (Esc 取消)", _KNOWLEDGE_MENU_OPTIONS, default_idx=0
    )
    if choice is None:
        return True

    if choice == "列出全部知识":
        for line in format_knowledge_list_grouped(loader):
            click.echo(line)
        return True

    if choice == "查看统计":
        for line in format_knowledge_stats(loader, curator):
            click.echo(line)
        return True

    if choice == "搜索知识":
        query = click.prompt("输入搜索关键词", type=str)
        matched = loader.match_by_keyword(query, limit=20)
        if not matched:
            click.echo(f"[INFO] 未找到匹配 '{query}' 的知识")
            return True
        for k in matched:
            prefix = _level_prefix(k)
            click.echo(f"[{prefix}] {k.name}: {k.description}")
        return True

    # 以下动作需二级菜单选知识名
    all_k = loader.list_all()
    if not all_k:
        click.echo("[INFO] 知识库为空，无知识可选")
        return True

    secondary = _build_secondary_options(loader)
    selected = ansi_select("选择知识 (Esc 取消)", secondary, default_idx=0)
    if selected is None:
        return True
    name = _parse_name_from_option(selected)

    if choice == "查看详情":
        k = loader.get(name)
        if k is None:
            click.echo(f"[ERR] 未找到知识: {name}")
            return True
        click.echo(f"[{_level_prefix(k)}] {k.name}: {k.description}")
        if k.tags:
            click.echo(f"tags: {', '.join(k.tags)}")
        click.echo("")
        click.echo(k.content)
        return True

    if choice == "固定知识":
        click.echo(handle_knowledge_pin(curator, name))
        return True

    if choice == "归档知识":
        click.echo(handle_knowledge_archive(curator, name))
        return True

    return True
