"""抓取结果本地保存。

目录结构:
    {output_root}/{source_id}/{YYYYMMDD}/
        ├── {url_hash}.html         # 原始 HTML
        ├── {url_hash}.md           # Crawl4AI 输出的 Markdown
        └── index.jsonl             # 元数据(每行一条 CrawlResult)
"""

from __future__ import annotations

import hashlib
import json
from datetime import date
from pathlib import Path

from loguru import logger

from .models import CrawlResult


def url_hash(url: str) -> str:
    """对 URL 取 SHA1,取前 16 位作为文件名。"""
    return hashlib.sha1(url.encode("utf-8")).hexdigest()[:16]


def build_output_dir(output_root: str | Path, source_id: str, day: date | None = None) -> Path:
    """构造保存目录: {output_root}/{source_id}/{YYYYMMDD}/。"""
    target_day = day or date.today()
    return Path(output_root) / source_id / target_day.strftime("%Y%m%d")


def save_result(
    result: CrawlResult,
    output_root: str | Path,
    day: date | None = None,
    *,
    skip_existing: bool = True,
) -> Path | None:
    """保存单条抓取结果到本地。

    返回 HTML 文件路径;失败结果只追加 index.jsonl,不写 HTML/MD,返回 None。

    skip_existing=True 时:如果当日该 URL 已保存(HTML 文件已存在),跳过写入,
    仅记录日志,返回已存在路径。保证增量抓取不会重复保存。
    """
    out_dir = build_output_dir(output_root, result.source_id, day)
    out_dir.mkdir(parents=True, exist_ok=True)

    h = url_hash(result.url)
    html_path: Path | None = None

    # 增量去重:如果当日已抓取过同一 URL,跳过
    existing_html = out_dir / f"{h}.html"
    if skip_existing and existing_html.exists():
        logger.debug("跳过重复 URL (今日已抓取): {} -> {}", result.url, h)
        return existing_html

    if result.success and result.html:
        html_path = out_dir / f"{h}.html"
        html_path.write_text(result.html, encoding="utf-8")

        if result.markdown:
            md_path = out_dir / f"{h}.md"
            md_path.write_text(result.markdown, encoding="utf-8")

    # 元数据(不含 html/markdown 大字段,避免 jsonl 巨大)
    meta = result.model_dump(exclude={"html", "markdown"}, mode="json")
    meta["url_hash"] = h
    meta["html_file"] = html_path.name if html_path else None

    index_path = out_dir / "index.jsonl"
    with index_path.open("a", encoding="utf-8") as f:
        f.write(json.dumps(meta, ensure_ascii=False) + "\n")

    logger.debug("已保存抓取结果: {}", result.short_summary())
    return html_path


def load_seen_urls(source_id: str, output_root: str | Path = "data/raw") -> set[str]:
    """加载某个源已抓取的所有 URL hash(跨日期累积)。

    读取 {output_root}/{source_id}/seen_urls.txt,每行一个 url_hash。
    """
    seen_path = Path(output_root) / source_id / "seen_urls.txt"
    if not seen_path.is_file():
        return set()
    with seen_path.open("r", encoding="utf-8") as f:
        return {line.strip() for line in f if line.strip()}


def mark_url_seen(source_id: str, url: str, output_root: str | Path = "data/raw") -> None:
    """追加一个已抓取 URL 的 hash 到 seen_urls.txt。"""
    seen_path = Path(output_root) / source_id / "seen_urls.txt"
    seen_path.parent.mkdir(parents=True, exist_ok=True)
    h = url_hash(url)
    with seen_path.open("a", encoding="utf-8") as f:
        f.write(h + "\n")
