"""Optional privilege classifier as a configured endpoint (R-12), with silent degrade.

Runs only when the user sets --privilege-endpoint / PRIVSWEEP_PRIVILEGE_ENDPOINT. Calls
an OpenAI-compatible chat-completions endpoint; per text chunk the endpoint returns
instruction-JSON {label, confidence, reason} over privileged, work_product,
not_privileged, review. No weights are bundled. When the endpoint is unreachable the
tier degrades to a warning without failing the run. Deterministic banner detection (R-5)
is independent of this tier.
"""
from __future__ import annotations

import json
import urllib.request
from typing import Optional

from .models import Finding, Report, Severity

INSTRUCTION = (
    "You are a privilege classifier for legal documents. For the user's text, respond "
    "ONLY with a JSON object: "
    '{"label": one of ["privileged","work_product","not_privileged","review"], '
    '"confidence": a number 0..1, "reason": "a short justification"}. '
    "privileged = attorney-client communication; work_product = the firm's own "
    "analysis or strategy; not_privileged = public, filed, or third-party records; "
    "review = unsure. Bias to review when unsure."
)
_LABEL_SEVERITY = {
    "privileged": Severity.HIGH,
    "work_product": Severity.HIGH,
    "review": Severity.MEDIUM,
}


def _chunks(text: str, size: int = 2000) -> list[str]:
    paras = [p for p in text.split("\n\n") if p.strip()]
    if not paras:
        return [text] if text.strip() else []
    chunks: list[str] = []
    cur = ""
    for p in paras:
        if cur and len(cur) + len(p) + 2 > size:
            chunks.append(cur)
            cur = p
        else:
            cur = f"{cur}\n\n{p}" if cur else p
    if cur:
        chunks.append(cur)
    return chunks


def classify_chunk(endpoint: str, key: Optional[str], chunk: str,
                   timeout: float = 15.0) -> dict:
    payload = {
        "model": "privilege",
        "messages": [
            {"role": "system", "content": INSTRUCTION},
            {"role": "user", "content": chunk},
        ],
        "temperature": 0,
    }
    headers = {"Content-Type": "application/json"}
    if key:
        headers["Authorization"] = f"Bearer {key}"
    req = urllib.request.Request(endpoint, data=json.dumps(payload).encode("utf-8"),
                                 headers=headers, method="POST")
    with urllib.request.urlopen(req, timeout=timeout) as resp:  # noqa: S310 (user URL)
        body = json.load(resp)
    content = body["choices"][0]["message"]["content"]
    return json.loads(content)


def augment_with_privilege(paths, report: Report, endpoint: str,
                           key: Optional[str] = None, *, timeout: float = 15.0) -> None:
    from .engine import _effective_kind, _normalize_paths, walk_paths
    from .extract import extract

    for fp in walk_paths(_normalize_paths(paths)):
        if _effective_kind(fp, None) in (None, "image", "eml"):
            continue
        try:
            doc = extract(fp)
        except Exception:  # noqa: BLE001
            continue
        for i, chunk in enumerate(_chunks(doc.full_text), 1):
            try:
                result = classify_chunk(endpoint, key, chunk, timeout=timeout)
            except Exception as exc:  # noqa: BLE001 - unreachable endpoint -> warn only
                report.note(f"privilege endpoint unreachable "
                            f"({type(exc).__name__}); classifier skipped.")
                return
            label = str(result.get("label", "review"))
            if label == "not_privileged":
                continue
            report.add(Finding(
                detector="privilege.endpoint",
                type="privilege_classification",
                severity=_LABEL_SEVERITY.get(label, Severity.MEDIUM),
                file=fp,
                location=f"chunk {i}",
                preview=f"{label}: {result.get('reason', '')}"[:120],
                confidence=result.get("confidence"),
                detail={"label": label, "reason": result.get("reason")},
            ))
