"""解析目录页与文章页 HTML，构建结构化文章数据。"""

import re

from bs4 import BeautifulSoup

from converter import blocks_to_markdown
from config import DATE_OVERRIDES

# 「教你炒股票1：不会赢钱的经济人，只是废人！」
TITLE_RE = re.compile(r"^教你炒股票\s*([0-9]+)\s*[：:－\-]\s*(.+)$")
DATETIME_RE = re.compile(r"(\d{4}-\d{2}-\d{2})(?:\s+(\d{1,2}:\d{2}))?")
_WS_RE = re.compile(r"\s+")

# 用于自动打标签的缠论核心概念（多字、不易误判）
CONCEPTS = [
    "走势中枢",
    "中枢",
    "背驰",
    "买卖点",
    "分型",
    "线段",
    "区间套",
    "第三类买卖点",
    "第一类买点",
    "第二类买点",
    "走势类型",
]


def parse_index(html: str) -> list[int]:
    """从目录页提取所有文章的 p 编号（升序，去重，去掉 p=0 目录本身）。"""
    soup = BeautifulSoup(html, "lxml")
    nums: list[int] = []
    for a in soup.select("a.chan[href*='chanlun?p=']"):
        m = re.search(r"p=(\d+)", a.get("href", ""))
        if m:
            n = int(m.group(1))
            if n > 0:
                nums.append(n)
    return sorted(set(nums))


def _is_nav_paragraph(p) -> bool:
    """识别正文末尾「返回目录」的导航 <p>，排除掉。"""
    a = p.find("a", href=True)
    return bool(a and "chanlun" in a["href"] and "p=0" in a["href"])


def _make_tags(corpus: str) -> list[str]:
    found = [c for c in CONCEPTS if c in corpus]
    # 去重保序（「走势中枢」与「中枢」可能同时命中）
    seen: set[str] = set()
    unique: list[str] = []
    for c in found:
        if c not in seen:
            seen.add(c)
            unique.append(c)
    return ["教你炒股票"] + unique[:2]


def parse_article(html: str, p_num: int, resolve_image) -> dict:
    """解析单篇文章，返回符合 Vue ``Article`` 结构的字典。"""
    soup = BeautifulSoup(html, "lxml")
    container = soup.select_one("div.container-narrow")

    title_full = ""
    date = DATE_OVERRIDES.get(p_num)  # 源站个别篇目日期残缺，按已知准确值纠偏
    elements = []  # <hr> 之后的正文块（<p> 与块级 <img> 等，按文档顺序）
    if container is not None:
        h2 = container.find("h2")
        if h2:
            title_full = h2.get_text(strip=True)
        if date is None:
            h5 = container.find("h5")
            if h5:
                m = DATETIME_RE.search(h5.get_text())
                if m:
                    date = m.group(1) + (f" {m.group(2)}" if m.group(2) else "")
        seen_hr = False
        for el in container.find_all(recursive=False):
            if el.name == "hr":
                seen_hr = True
                continue
            if not seen_hr:
                continue  # 跳过标题/日期
            if el.name == "p" and _is_nav_paragraph(el):
                continue  # 排除文末「返回目录」
            elements.append(el)

    # 课次号 / 标题：从「教你炒股票N：标题」中拆分
    m = TITLE_RE.match(title_full)
    if m:
        lesson = int(m.group(1))
        topic = m.group(2).strip()
    else:
        lesson = p_num
        topic = title_full or f"教你炒股票 {p_num}"

    content = blocks_to_markdown(elements, resolve_image)

    # 纯文本度量：阅读时长与摘要（折叠源 HTML 的折行空白）
    plain_texts = [_WS_RE.sub(" ", el.get_text(" ", strip=True)) for el in elements]
    plain_texts = [t for t in plain_texts if t]
    plain_len = sum(len(t) for t in plain_texts)
    corpus = "".join(plain_texts)

    first_text = plain_texts[0] if plain_texts else ""
    excerpt = (first_text[:90] + "…") if len(first_text) > 90 else first_text
    reading_time = max(1, round(plain_len / 500))  # 中文技术文 ~500 字/分钟

    return {
        "id": f"cl-{p_num:03d}",
        "slug": f"ke-{p_num:03d}",
        "category": "chanlun",
        "title": topic,
        "subtitle": f"第 {lesson} 课 · 教你炒股票",
        "lesson": lesson,
        "date": date or "",
        "tags": _make_tags(corpus),
        "excerpt": excerpt,
        "readingTime": reading_time,
        "content": content,
    }
