"""M1 抓取入口脚本。

用法:
    uv run python -m scripts.run_crawler
    uv run python -m scripts.run_crawler --source cls
    uv run python -m scripts.run_crawler --config configs/sources.yaml --no-save
"""

from __future__ import annotations

import argparse
import asyncio
import sys
from pathlib import Path

from crawl4ai import AsyncWebCrawler, BrowserConfig
from loguru import logger

from crawler import crawl_all, crawl_source, load_crawler_config


def _setup_logger(level: str) -> None:
    """配置 loguru,输出到控制台与 logs/crawler.log。"""
    logger.remove()
    logger.add(sys.stderr, level=level, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {name} | {message}")
    log_path = Path("logs") / "crawler.log"
    log_path.parent.mkdir(parents=True, exist_ok=True)
    logger.add(
        log_path,
        level="DEBUG",
        rotation="10 MB",
        retention=5,
        encoding="utf-8",
        enqueue=True,
    )


async def _run(args: argparse.Namespace) -> int:
    config = load_crawler_config(args.config)

    if args.source:
        source = next((s for s in config.sources if s.id == args.source), None)
        if source is None:
            logger.error("未找到源 id={}", args.source)
            return 2
        if not source.enabled:
            logger.warning("源 {} 在 yaml 中标记为 disabled,本次仍将抓取", source.id)

        browser_config = BrowserConfig(
            headless=config.settings.headless,
            user_agent=config.settings.user_agent,
            verbose=False,
        )
        sem = asyncio.Semaphore(config.settings.concurrency)
        async with AsyncWebCrawler(config=browser_config) as crawler:
            results = await crawl_source(crawler, source, config.settings, sem, save=not args.no_save)
    else:
        results = await crawl_all(config, save=not args.no_save)

    succ = sum(1 for r in results if r.success)
    total = len(results)
    rate = succ / max(total, 1)
    logger.info("抓取结束 总 {} 成功 {} 成功率 {:.0%}", total, succ, rate)
    # 验收标准: 成功率 >= 90%
    return 0 if rate >= 0.9 else 1


def main() -> int:
    parser = argparse.ArgumentParser(description="A 股新闻抓取(M1)")
    parser.add_argument("--config", default="configs/sources.yaml", help="sources.yaml 路径")
    parser.add_argument("--source", default=None, help="只抓单个源 id,默认抓全部启用源")
    parser.add_argument("--no-save", action="store_true", help="不写入本地文件,仅试跑")
    parser.add_argument("--log-level", default="INFO", help="DEBUG/INFO/WARNING/ERROR")
    args = parser.parse_args()

    _setup_logger(args.log_level)
    return asyncio.run(_run(args))


if __name__ == "__main__":
    raise SystemExit(main())
