import re
import httpx
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional

router = APIRouter(prefix="/dataset")

# ── Known URL column names across popular datasets ────────────────────────────

URL_COLUMN_HINTS = {
    "url", "source", "source_url", "webpage_url", "page_url",
    "link", "file_path", "image_url", "audio_url", "video_url",
    "origin", "origin_url", "document_url", "article_url",
    "uri", "href", "canonical_url", "permalink",
}

URL_REGEX = re.compile(
    r"^https?://.{4,}",
    re.IGNORECASE,
)


# ── Request models ────────────────────────────────────────────────────────────

class ProvenanceRequest(BaseModel):
    hf_id: Optional[str] = None
    file_name: Optional[str] = None
    file_last_modified: Optional[int] = None   # ms epoch from browser File.lastModified
    columns: list[str] = []
    sample: list[dict] = []                    # up to 20 rows to scan for URL columns


# ── Helpers ───────────────────────────────────────────────────────────────────

def _detect_url_columns(columns: list[str], sample: list[dict]) -> list[str]:
    """
    Return column names that are likely source URL columns.
    Two signals: name matches known hints, OR majority of sample values look like URLs.
    """
    found = []
    col_lower = {c: c.lower().replace("-", "_") for c in columns}

    for col, col_l in col_lower.items():
        # Signal 1: name hint
        if col_l in URL_COLUMN_HINTS or any(h in col_l for h in ("url", "uri", "link", "href", "source")):
            found.append(col)
            continue

        # Signal 2: value pattern — check if >60% of non-null sample values look like URLs
        if sample:
            vals = [str(row.get(col, "")) for row in sample if row.get(col)]
            if vals:
                url_count = sum(1 for v in vals if URL_REGEX.match(v))
                if url_count / len(vals) > 0.6:
                    found.append(col)

    return list(dict.fromkeys(found))  # dedup, preserve order


def _parse_card_data(card_data: dict) -> dict:
    """Extract structured fields from HF dataset card YAML blob."""
    return {
        "pretty_name":           card_data.get("pretty_name"),
        "license":               card_data.get("license"),
        "languages":             card_data.get("language", []),
        "task_categories":       card_data.get("task_categories", []),
        "task_ids":              card_data.get("task_ids", []),
        "annotations_creators":  card_data.get("annotations_creators", []),
        "source_datasets":       card_data.get("source_datasets", []),
        "size_categories":       card_data.get("size_categories", []),
        "multilinguality":       card_data.get("multilinguality", []),
        "tags":                  card_data.get("tags", []),
    }


# ── /dataset/provenance ───────────────────────────────────────────────────────

@router.post("/provenance")
async def dataset_provenance(req: ProvenanceRequest):
    result = {
        "url_columns":        [],
        "dataset_level":      None,
        "file_level":         None,
    }

    # ── Per-example: detect URL columns ──────────────────────────────────────
    result["url_columns"] = _detect_url_columns(req.columns, req.sample)

    # ── HuggingFace dataset-level metadata ────────────────────────────────────
    if req.hf_id:
        try:
            async with httpx.AsyncClient(timeout=10) as client:
                r = await client.get(
                    f"https://huggingface.co/api/datasets/{req.hf_id}",
                    headers={"Accept": "application/json"},
                )
            if r.status_code == 200:
                data = r.json()
                card = _parse_card_data(data.get("cardData") or {})
                result["dataset_level"] = {
                    "hf_id":          req.hf_id,
                    "pretty_name":    card["pretty_name"] or req.hf_id,
                    "created_at":     data.get("createdAt"),
                    "last_modified":  data.get("lastModified"),
                    "downloads":      data.get("downloads"),
                    "likes":          data.get("likes"),
                    "license":        card["license"],
                    "languages":      card["languages"],
                    "task_categories":card["task_categories"],
                    "source_datasets":card["source_datasets"],
                    "size_categories":card["size_categories"],
                    "tags":           card["tags"],
                    "annotations_creators": card["annotations_creators"],
                    "hf_url":         f"https://huggingface.co/datasets/{req.hf_id}",
                    "download_url":   f"https://huggingface.co/datasets/{req.hf_id}/resolve/main/",
                }
        except Exception as e:
            result["dataset_level"] = {"error": str(e)}

    # ── Upload file-level metadata ────────────────────────────────────────────
    if req.file_name:
        import datetime
        last_mod = None
        if req.file_last_modified:
            last_mod = datetime.datetime.utcfromtimestamp(
                req.file_last_modified / 1000
            ).isoformat() + "Z"

        result["file_level"] = {
            "file_name":     req.file_name,
            "last_modified": last_mod,
            "note":          "Scrape date and origin URL unavailable for direct uploads unless present in data columns.",
        }

    return result