# -*- coding: utf-8 -*-
"""当日抓取器 - 针对指定板块抓取当日含关键字的帖子"""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime
from zoneinfo import ZoneInfo

from . import config
from .fetcher import ForumFetcher
from .forum_thread import parse_thread_posts
from .forum_topics import parse_topic_list
from .parsers import get_parser
from .parsers.base import PriceRecord

ASIA_SHANGHAI = ZoneInfo("Asia/Shanghai")


@dataclass(slots=True)
class MatchedPost:
    """匹配关键字并解析后的帖子"""
    topic_id: int
    board_id: int
    title: str
    url: str
    author_name: str
    last_update_time: datetime
    matched_keyword: str
    post_text: str
    coin_records: list[PriceRecord] = field(default_factory=list)


def _match_keywords(text: str) -> str | None:
    """返回命中的第一个关键字，未命中返回 None"""
    for kw in config.KEYWORDS:
        if kw in text:
            return kw
    return None


def _build_board_url(board_id: int) -> str:
    return f"/index.asp?boardid={board_id}"


def crawl_board_today(
    fetcher: ForumFetcher,
    db,
    board_id: int,
    trade_date: str,
    sample_mode: bool = False,
    max_pages: int = 10,
) -> list[MatchedPost]:
    """抓取指定板块当天的匹配帖子。

    sample_mode=True 时仅存原始帖子正文，不做价格解析。
    """
    matched_posts: list[MatchedPost] = []
    page = 1
    board_url = _build_board_url(board_id)

    while page <= max_pages:
        page_url = f"{board_url}&page={page}"
        print(f"[crawl] 抓取板块{board_id}第{page}页...")
        try:
            html, _ = fetcher.get(page_url)
        except RuntimeError as exc:
            print(f"[warn] 板块{board_id}第{page}页抓取失败: {exc}")
            break

        print(f"[crawl] 解析主题列表...")
        topics = parse_topic_list(html, board_id, fetcher.config.base_url)
        print(f"[crawl] 发现{len(topics)}个主题")
        if not topics:
            break

        # 日期过滤：只保留当天的主题
        today_topics = [
            t for t in topics
            if t.last_update_time.astimezone(ASIA_SHANGHAI).strftime("%Y-%m-%d") == trade_date
        ]
        print(f"[crawl] 当日主题: {len(today_topics)}个")
        if not today_topics:
            break

        for topic in today_topics:
            # 第一层：标题关键字过滤
            title_kw = _match_keywords(topic.title)
            if not title_kw:
                continue

            print(f"[crawl] 命中标题关键字 '{title_kw}': {topic.title[:40]}")
            # 抓取帖子页
            try:
                topic_html, _ = fetcher.get(topic.url)
            except RuntimeError as exc:
                print(f"[warn] 主题抓取失败 topic_id={topic.topic_id}: {exc}")
                continue

            posts = parse_thread_posts(
                html=topic_html,
                base_url=fetcher.config.base_url,
                default_author_key=topic.author_key,
                default_author_name=topic.author_name,
                default_profile_url=topic.profile_url,
            )

            # 取首楼正文
            post_text = posts[0].text if posts else ""
            if not post_text:
                continue

            # 第二层：正文关键字过滤（标题已命中，正文也检查）
            content_kw = _match_keywords(post_text)
            matched_kw = content_kw or title_kw

            if sample_mode:
                # 样本模式：仅存原始帖子
                db.save_raw_post({
                    "trade_date": trade_date,
                    "board_id": board_id,
                    "topic_id": topic.topic_id,
                    "title": topic.title,
                    "url": topic.url,
                    "author_name": topic.author_name,
                    "post_text": post_text,
                })
                matched_posts.append(MatchedPost(
                    topic_id=topic.topic_id,
                    board_id=board_id,
                    title=topic.title,
                    url=topic.url,
                    author_name=topic.author_name,
                    last_update_time=topic.last_update_time,
                    matched_keyword=matched_kw,
                    post_text=post_text,
                ))
                continue

            # 常规模式：解析价格
            parser_func = get_parser(board_id)
            records: list[PriceRecord] = []
            if parser_func:
                try:
                    records = parser_func(post_text)
                except Exception as exc:
                    print(f"[warn] 解析失败 topic_id={topic.topic_id}: {exc}")

            # 写入数据库
            board_type = config.BOARD_TYPE.get(board_id, "")
            fetched_at = datetime.now(ASIA_SHANGHAI).isoformat()
            for rec in records:
                db.save_price_record({
                    "trade_date": trade_date,
                    "board_id": board_id,
                    "board_type": board_type,
                    "topic_id": topic.topic_id,
                    "topic_title": topic.title,
                    "topic_url": topic.url,
                    "author_name": topic.author_name,
                    "name": rec.name,
                    "ref_price": rec.ref_price,
                    "price_details": rec.price_details,
                    "unit": rec.unit,
                    "quantity": rec.quantity,
                    "quantity_unit": rec.quantity_unit,
                    "package_req": rec.package_req,
                    "quality_req": rec.quality_req,
                    "other_notes": rec.other_notes,
                    "raw_text": rec.raw_text,
                    "fetched_at": fetched_at,
                })

            matched_posts.append(MatchedPost(
                topic_id=topic.topic_id,
                board_id=board_id,
                title=topic.title,
                url=topic.url,
                author_name=topic.author_name,
                last_update_time=topic.last_update_time,
                matched_keyword=matched_kw,
                post_text=post_text,
                coin_records=records,
            ))

        page += 1

    return matched_posts


def save_sample_file(matched_posts: list[MatchedPost], board_id: int, sample_dir: str) -> str:
    """将匹配帖子正文写入样本文件，供设计解析器参考"""
    import os
    os.makedirs(sample_dir, exist_ok=True)
    path = os.path.join(sample_dir, f"board{board_id}_samples.txt")
    with open(path, "w", encoding="utf-8") as f:
        for i, post in enumerate(matched_posts, 1):
            f.write(f"{'=' * 60}\n")
            f.write(f"样本 {i}: {post.title}\n")
            f.write(f"URL: {post.url}\n")
            f.write(f"作者: {post.author_name}\n")
            f.write(f"命中关键字: {post.matched_keyword}\n")
            f.write(f"更新时间: {post.last_update_time}\n")
            f.write(f"{'-' * 60}\n")
            f.write(post.post_text + "\n\n")
    return path
