"""Workflow: Detail-Ansicht einer einzelnen Rechnung.

Aufruf:
  python get_document.py --uid 12345
  python get_document.py --uid 12345 --format json
  python get_document.py --uid 12345 --transactions --line-items

Ruft `getOneDocument` auf und gibt die Meta-Daten aus. Der API-Response
enthält zusätzlich `fileContent` (base64-PDF) — dieses Feld wird
GRUNDSAETZLICH herausgefiltert und niemals geloggt, gedruckt oder im
Output gezeigt. Wer das PDF braucht, nutzt `download_documents.py`.

Optionale Felder via Flags:
  --line-items     Line-Items mit anfragen (loadLineItems=true)
  --transactions   Verknuepfte Transaktionen mit anfragen (transactions=true)
  --approval       Approval-Status mit anfragen (documentApproval=true)
  --readable-text  OCR-Text mit anfragen (readableText=true)

Hinweis: `includeDocument` (=fileContent) wird NIE gesetzt — es bringt
nichts außer Risiko, dass der base64-Blob im LLM-Kontext landet.
"""
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path
from typing import Any

try:
    sys.stdout.reconfigure(encoding="utf-8")
except (AttributeError, Exception):
    pass

sys.path.insert(0, str(Path(__file__).parent.parent))

from gmi_client import GmiClient, GmiHttpError  # noqa: E402
from workflows._safety import _strip_forbidden, FORBIDDEN_FIELDS  # noqa: E402,F401


# ---------- Fetcher ----------

# Rückwärts-kompatibler Alias für Tests, die den privaten Namen referenzieren.
_FORBIDDEN_FIELDS = set(FORBIDDEN_FIELDS)


def get_document(
    client: GmiClient,
    uid: int,
    line_items: bool = False,
    transactions: bool = False,
    approval: bool = False,
    readable_text: bool = False,
) -> dict:
    """Liest eine einzelne Rechnung. Filtert fileContent zwingend raus.

    Returns:
      {ok: True, documentUid, meta_data, [line_items, transactions, ...]}
      {ok: False, error: 'not_found' | 'http_<status>', detail: ...}
    """
    params: dict[str, Any] = {"documentUid": uid}
    if line_items:
        params["loadLineItems"] = True
    if transactions:
        params["transactions"] = True
    if approval:
        params["documentApproval"] = True
    if readable_text:
        params["readableText"] = True
    # WICHTIG: includeDocument NIE setzen — würde fileContent zurückliefern.

    try:
        raw = client.call("getOneDocument", **params)
    except GmiHttpError as e:
        if e.status == 404:
            return {"ok": False, "error": "not_found", "documentUid": uid}
        return {"ok": False, "error": f"http_{e.status}", "detail": str(e),
                "documentUid": uid}

    if not isinstance(raw, dict):
        return {"ok": False, "error": "unexpected_response_type",
                "documentUid": uid}

    # Defensiv: gesamtes Response durch Strip-Filter, danach extrahieren.
    safe = _strip_forbidden(raw)
    meta = safe.get("meta_data") or {}

    out: dict[str, Any] = {
        "ok": True,
        "documentUid": uid,
        "meta_data": meta,
    }
    # Optionale Subobjekte aus dem Top-Level übernehmen, falls vorhanden.
    for k in ("line_items", "lineItems", "transactions", "approval", "readableText"):
        if k in safe:
            out[k] = safe[k]
    return out


# ---------- Formatter ----------

def _fmt_amount(val) -> str:
    if val is None:
        return ""
    try:
        return f"{float(val):.2f}".replace(".", ",")
    except (TypeError, ValueError):
        return str(val)


def format_markdown(data: dict) -> str:
    if not data.get("ok"):
        return format_error_md(data)

    meta = data.get("meta_data", {})
    lines = [f"# Rechnung {meta.get('documentNumber', '?')}", ""]

    # Kopf-Block
    rows = [
        ("documentUid", data["documentUid"]),
        ("Lieferant", meta.get("companyName")),
        ("companyUid", meta.get("companyUid")),
        ("Datum", meta.get("documentDate")),
        ("Faelligkeit", meta.get("documentDueDate")),
        ("Bezahlt am", meta.get("paidAt")),
        ("Brutto", _fmt_amount(meta.get("grossAmount")) + (
            f" {meta.get('currency', '')}" if meta.get("grossAmount") is not None else "")),
        ("Netto", _fmt_amount(meta.get("netAmount")) + (
            f" {meta.get('currency', '')}" if meta.get("netAmount") is not None else "")),
        ("MwSt", _fmt_amount(meta.get("vat"))),
        ("Status", meta.get("paymentStatus")),
        ("Typ", meta.get("documentType")),
        ("Dateiname", meta.get("filename")),
        ("Tags", ", ".join(meta.get("tags", []) or []) if meta.get("tags") else ""),
        ("Notiz", meta.get("note")),
        ("Bestellnummer", meta.get("orderNumber")),
        ("Quelle", meta.get("source")),
        ("Archiviert", meta.get("isArchived")),
    ]
    for label, val in rows:
        if val not in (None, "", []):
            lines.append(f"- **{label}:** {val}")

    # Optionale Sub-Sektionen
    line_items = data.get("line_items") or data.get("lineItems")
    if line_items:
        lines.append("")
        lines.append("## Line Items")
        lines.append("")
        lines.append("```json")
        lines.append(json.dumps(line_items, indent=2, ensure_ascii=False))
        lines.append("```")

    if data.get("transactions"):
        lines.append("")
        lines.append("## Verknuepfte Transaktionen")
        lines.append("")
        lines.append("```json")
        lines.append(json.dumps(data["transactions"], indent=2, ensure_ascii=False))
        lines.append("```")

    if data.get("approval"):
        lines.append("")
        lines.append("## Approval")
        lines.append("")
        lines.append("```json")
        lines.append(json.dumps(data["approval"], indent=2, ensure_ascii=False))
        lines.append("```")

    if data.get("readableText"):
        lines.append("")
        lines.append("## OCR-Text")
        lines.append("")
        lines.append("```")
        lines.append(str(data["readableText"]))
        lines.append("```")

    return "\n".join(lines)


def format_error_md(data: dict) -> str:
    return f"## Fehler\n\n```json\n{json.dumps(data, indent=2, ensure_ascii=False, default=str)}\n```"


# ---------- CLI ----------

def _print(data: dict, args: argparse.Namespace) -> None:
    if args.format == "json":
        print(json.dumps(data, indent=2, ensure_ascii=False, default=str))
    else:
        print(format_markdown(data))


def main() -> int:
    p = argparse.ArgumentParser()
    p.add_argument("--uid", type=int, required=True, help="documentUid der Rechnung")
    p.add_argument("--line-items", dest="line_items", action="store_true",
                   help="Line-Items zusätzlich anfragen")
    p.add_argument("--transactions", action="store_true",
                   help="Verknuepfte Transaktionen anfragen")
    p.add_argument("--approval", action="store_true",
                   help="Approval-Status anfragen")
    p.add_argument("--readable-text", dest="readable_text", action="store_true",
                   help="OCR-Text anfragen")
    p.add_argument("--format", choices=["json", "markdown"], default="markdown")
    args = p.parse_args()

    try:
        client = GmiClient()
    except Exception as e:
        print(json.dumps({"error": "config", "detail": str(e)}))
        return 1

    data = get_document(
        client,
        uid=args.uid,
        line_items=args.line_items,
        transactions=args.transactions,
        approval=args.approval,
        readable_text=args.readable_text,
    )
    _print(data, args)
    return 0 if data.get("ok") else 1


if __name__ == "__main__":
    sys.exit(main())
