"""Orchestrator — builds queries, runs sources, computes signal."""

from __future__ import annotations

import re
import time
from datetime import datetime, timezone

from priorart import __version__
from priorart.scoring import compute_signal
from priorart.sources.github import search_repos
from priorart.sources.hn import search_discussions


def build_queries(title: str, body: str = "") -> list[str]:
    """Build search queries from the idea title (and optional body).

    Uses the title directly plus cleaned variants.
    The title IS the idea description — no LLM needed.
    """
    clean = title.strip()
    for prefix in ["idea:", "idea -", "[idea]"]:
        if clean.lower().startswith(prefix):
            clean = clean[len(prefix) :].strip()

    queries: list[str] = []
    seen: set[str] = set()

    def add(q: str) -> None:
        q = q.strip()
        if q and q.lower() not in seen:
            seen.add(q.lower())
            queries.append(q)

    # Split on common separators
    parts = [clean]
    for sep in [" — ", " - ", " – ", " | "]:
        if sep in clean:
            parts = [p.strip() for p in clean.split(sep) if p.strip()]
            break

    for part in parts:
        stripped = re.sub(r"\([^)]*\)", "", part).strip()
        stripped = re.sub(r"[^\w\s-]", " ", stripped).strip()
        stripped = re.sub(r"\s+", " ", stripped)
        if stripped:
            if len(stripped.split()) <= 1 and len(parts) > 1:
                continue
            add(stripped)

    full = " ".join(queries)
    words = full.split()
    if len(words) > 5:
        add(" ".join(words[:5]))
        add(" ".join(words[:3]))

    if body:
        for line in body.split("\n"):
            line = line.strip().strip("#").strip("-").strip("*").strip()
            if len(line) > 10 and not line.startswith(("http", "![", "<!--")):
                body_clean = re.sub(r"[^\w\s-]", " ", line).strip()
                body_clean = re.sub(r"\s+", " ", body_clean)
                body_words = body_clean.split()
                if len(body_words) >= 3:
                    add(" ".join(body_words[:6]))
                    break

    return queries


def scan(
    idea: str,
    github_token: str | None = None,
    sources: list[str] | None = None,
    body: str = "",
) -> dict:
    """Run a full prior-art scan and return structured results.

    Args:
        idea: The idea description to scan.
        github_token: GitHub personal access token (required for GitHub source).
        sources: List of source names to query. Defaults to ["github", "hn"].
        body: Optional body text for additional query extraction.

    Returns:
        Structured dict: {query, queries, sources, signal, meta}
    """
    if sources is None:
        sources = ["github", "hn"]

    queries = build_queries(idea, body)

    all_repos: list[dict] = []
    all_hn: list[dict] = []
    seen_repo_names: set[str] = set()
    seen_hn_urls: set[str] = set()

    for query in queries:
        if "github" in sources:
            repos = search_repos(query, github_token)
            for r in repos:
                if r["name"] not in seen_repo_names:
                    seen_repo_names.add(r["name"])
                    all_repos.append(r)
            time.sleep(1)

        if "hn" in sources:
            hn = search_discussions(query)
            for h in hn:
                if h["url"] not in seen_hn_urls:
                    seen_hn_urls.add(h["url"])
                    all_hn.append(h)
            time.sleep(0.5)

    all_repos.sort(key=lambda r: r["stars"], reverse=True)
    all_hn.sort(key=lambda h: h["points"], reverse=True)

    signal = compute_signal(all_repos, all_hn)

    source_results = []
    if "github" in sources:
        source_results.append({"type": "github", "results": all_repos})
    if "hn" in sources:
        source_results.append({"type": "hn", "results": all_hn})

    return {
        "query": idea,
        "queries": queries,
        "sources": source_results,
        "signal": signal,
        "meta": {
            "timestamp": datetime.now(timezone.utc).isoformat(),
            "version": __version__,
        },
    }
