#!/usr/bin/env python
"""Check markdown file semantic quality via DeepSeek API.

Uses DEEPSEEK_API_KEY from environment.
Analyzes the markdown and returns structured JSON with:
- understandable: boolean — can an LLM reliably extract facts from this?
- confidence: "sure" | "high" | "maybe" | "cannot_understand"
- value_alignment_score: 1-5 — how well are values assigned to their headings/categories?
- issues: list[str] — specific problems found (disconnected values, missing context, etc.)
- summary: str — one-sentence assessment
"""

from __future__ import annotations

import json
import os
import sys
import time
from pathlib import Path

import requests

MODEL = "deepseek-v4-flash"
URL = "https://api.deepseek.com/v1/chat/completions"


def analyze_markdown(md_path: str | Path, max_chars: int = 8000) -> dict:
    md_path = Path(md_path)
    if not md_path.exists():
        return {"error": f"File not found: {md_path}", "path": str(md_path), "understandable": False, "confidence": "cannot_understand"}

    api_key = os.environ.get("DEEPSEEK_API_KEY", "")
    if not api_key:
        return {"error": "DEEPSEEK_API_KEY not set", "path": str(md_path), "understandable": False, "confidence": "cannot_understand"}

    text = md_path.read_text(encoding="utf-8")
    if len(text) > max_chars:
        text = text[:max_chars] + "\n\n[... content truncated ...]"

    prompt = f"""Analyze this markdown file from a web crawler converted from HTML.

Rate how well an LLM could understand and extract factual information.

Check: Can values/numbers be assigned to their labels? Are there orphaned values? Are tables preserved?

You MUST output EXACTLY this JSON structure (no other fields, no markdown):

{{"understandable": true, "confidence": "sure", "value_alignment_score": 5, "issues": ["example issue"], "summary": "one sentence"}}

- understandable: true if facts can be extracted, false if too scrambled
- confidence: "sure", "high", "maybe", or "cannot_understand"
- value_alignment_score: integer 1 (scrambled) to 5 (perfectly clear)
- issues: list of problem strings (empty list if none)
- summary: one sentence describing overall quality

Markdown:
{text[:6000]}"""

    headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
    payload = {
        "model": MODEL,
        "max_tokens": 4096,
        "temperature": 0.1,
        "response_format": {"type": "json_object"},
        "messages": [{"role": "user", "content": prompt}],
    }

    started = time.perf_counter()
    for attempt in range(3):
        try:
            r = requests.post(URL, headers=headers, json=payload, timeout=60)
            if r.status_code == 200:
                data = r.json()
                choice = data["choices"][0]["message"]
                content = choice.get("content", "") or ""
                if not content and not choice.get("reasoning_content"):
                    if attempt < 2:
                        time.sleep(1)
                        continue
                raw = content.strip()
                if raw.startswith("```"):
                    raw = raw.split("\n", 1)[1] if "\n" in raw else raw[3:]
                    if raw.endswith("```"):
                        raw = raw[:-3]
                    raw = raw.strip()
                if raw:
                    result = json.loads(raw)
                    result["_elapsed_s"] = round(time.perf_counter() - started, 2)
                    result["_model"] = MODEL
                    result["_path"] = str(md_path)
                    return result
            elif r.status_code in (429, 500, 502, 503, 504):
                delay = 2 * (2 ** attempt)
                time.sleep(delay)
        except json.JSONDecodeError:
            if attempt < 2:
                time.sleep(1)
        except Exception:
            if attempt < 2:
                time.sleep(1)

    elapsed = round(time.perf_counter() - started, 2)
    return {
        "understandable": False,
        "confidence": "cannot_understand",
        "value_alignment_score": 1,
        "issues": ["DeepSeek API failed after 3 attempts"],
        "summary": "API failure",
        "_elapsed_s": elapsed,
        "_model": MODEL,
        "_path": str(md_path),
    }


def check_all_markdown(out_dir: str | Path) -> list[dict]:
    out_dir = Path(out_dir)
    md_files = sorted(out_dir.glob("*.md"))
    md_files = [f for f in md_files if "_removed_parts" not in f.name]
    results = []
    for md_path in md_files:
        print(f"Analyzing {md_path.name}...")
        result = analyze_markdown(md_path)
        result["page_stem"] = md_path.stem
        results.append(result)
        json_path = md_path.with_suffix("").with_suffix(md_path.suffix + "_quality.json")
        json_path.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
    return results


def main() -> int:
    import argparse
    p = argparse.ArgumentParser(description="Check markdown semantic quality via DeepSeek")
    p.add_argument("path", nargs="?", help="Single .md file or directory of .md files")
    p.add_argument("--json", action="store_true", help="Output raw JSON only")
    args = p.parse_args()

    if not args.path:
        p.print_help()
        return 1

    target = Path(args.path)
    if target.is_dir():
        results = check_all_markdown(target)
    else:
        result = analyze_markdown(target)
        results = [result]

    if args.json:
        print(json.dumps(results, ensure_ascii=False, indent=2))
        return 0

    sure = sum(1 for r in results if r.get("confidence") == "sure")
    high = sum(1 for r in results if r.get("confidence") == "high")
    maybe = sum(1 for r in results if r.get("confidence") == "maybe")
    cant = sum(1 for r in results if r.get("confidence") == "cannot_understand")

    print(f"\n{len(results)} markdown files analyzed:")
    print(f"  sure:                {sure}")
    print(f"  high:                {high}")
    print(f"  maybe:               {maybe}")
    print(f"  cannot_understand:   {cant}")
    for r in results:
        name = r.get("page_stem", r.get("_path", "?"))
        conf = r.get("confidence", "?")
        score = r.get("value_alignment_score", "?")
        issues = r.get("issues", [])
        issue_str = f" ({'; '.join(issues[:2])})" if issues else ""
        print(f"  [{conf}] {name}  align={score}/5{issue_str}")

    return 0 if cant == 0 else 1


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