"""Generator für die Fabric „API for GraphQL"-Dokumentation.

Definition-basiert (analog zu :mod:`core.copyjob_doc_generator`): die Definition
beschreibt die angebundenen Datenquellen und das GraphQL-Schema. Rendering aus
einem :class:`~core.models.GraphQlApiInfo`.
"""
from __future__ import annotations

from core.models import GraphQlApiInfo, GraphQlDataSourceInfo
from core.template_renderer import TemplateRenderer
from core.workspace_doc_generator import _escape_cell, ensure_template, load_template

GRAPHQLAPI_TEMPLATE_FILENAME = "WorkspaceGraphQLApivorlage.md"

_MAX_SCHEMA_CHARS = 4000

__all__ = [
    "GRAPHQLAPI_TEMPLATE_FILENAME",
    "DEFAULT_GRAPHQLAPI_TEMPLATE",
    "ensure_template",
    "load_template",
    "build_datasources_table",
    "build_schema_block",
    "build_service_hint",
    "build_graphqlapi_values",
    "render_graphqlapi",
]


DEFAULT_GRAPHQLAPI_TEMPLATE = """# Microsoft Fabric API-for-GraphQL-Dokumentation

> **Hinweis:** Diese Dokumentation ist verpflichtend für alle Produktiv-GraphQL-APIs.
> Nicht relevante Kapitel können leer bleiben, dürfen jedoch nicht entfernt werden.
> Automatisch befüllte Felder stammen aus dem Microsoft Fabric Service; mit
> _„Manuell zu ergänzen"_ markierte Felder sind fachlich zu vervollständigen.

---

## 1. Metadaten

| Feld | Wert |
|-----|------|
| GraphQL-API-Name | {{GQ_Name}} |
| Beschreibung | {{GQ_Beschreibung}} |
| GraphQL-API-ID | {{GQ_ID}} |
| Web-URL | {{GQ_WebUrl}} |
| Anzahl Datenquellen | {{GQ_AnzahlDatenquellen}} |
| Erstellt / konfiguriert von | {{GQ_ConfiguredBy}} |
| Zuletzt geändert | {{GQ_ModifiedTime}} |
| Fachbereich | {{GQ_Fachbereich}} |
| Konzerndomäne | {{GQ_Konzerndomaene}} |
| Aktuelle Version | 1.0 |
| Status | Produktiv |
| Letzte Aktualisierung | {{GQ_ExportDatum}} |

---

## 2. Ansprechpartner & Verantwortlichkeiten

| Rolle | Name / Team | Kontakt |
|-----|-------------|--------|
| Fachlicher Owner | {{KONTAKT_BusinessOwner}} | {{KONTAKT_BusinessOwnerMail}} |
| Technischer Owner | {{KONTAKT_TechOwner}} | {{KONTAKT_TechOwnerMail}} |
| Data Steward | {{KONTAKT_DataSteward}} | {{KONTAKT_DataStewardMail}} |
| Betrieb / Support | {{KONTAKT_Betrieb}} | {{KONTAKT_BetriebMail}} |

---

## 3. Business-Ziel & fachlicher Kontext

### 3.1 Zielsetzung
{{GQ_Zielsetzung}}

### 3.2 Fachlicher Anwendungsfall
{{GQ_Anwendungsfall}}

### 3.3 Nachgelagerte Verbraucher (Anwendungen / Dienste)
{{GQ_Konsumenten}}

---

## 4. Aufbau & Struktur

### 4.1 Angebundene Datenquellen

{{GQ_DatenquellenTabelle}}

### 4.2 GraphQL-Schema

{{GQ_SchemaBlock}}

---

## 5. Datenquellen & Beladung

### 5.1 Datenquellen-Details

{{GQ_DatenquellenTabelle2}}

### 5.2 Detailbeschreibung je Datenquelle
{{GQ_DatenquellenDetail}}

---

## 6. Inhalt & Nutzung

{{GQ_ServiceHinweis}}

### 6.1 Nutzung der API
{{GQ_VerwendungHinweis}}

### 6.2 Parameter & Konfiguration
{{GQ_ParameterHinweis}}

### 6.3 Datenqualität

- Umgang mit Fehlern: {{GQ_NullHandling}}
- Datenvalidierungsregeln: {{GQ_Validierungsregeln}}
- Aufbewahrung / Historisierung: {{GQ_Aufbewahrung}}

### 6.4 Performance-Hinweise

- Query-Komplexität / Optimierung: {{GQ_Optimierung}}
- Bekannte Performance-Engpässe: {{GQ_PerformanceHinweise}}
- Weitere Maßnahmen: {{GQ_Optimierungen}}

---

## 7. Betrieb & Wartung

### 7.1 Betrieb & Orchestrierung

{{GQ_Beladung}}

### 7.2 Monitoring & Fehlerbehandlung
{{GQ_Monitoring}}

### 7.3 Bekannte Probleme / Technische Schulden
{{GQ_BekannteProbleme}}

---

## 8. Sicherheit & Berechtigungen

### 8.1 Zugriff & Freigaben
{{GQ_Zugriffe}}

### 8.2 Sensitivity Labels
{{GQ_Labels}}

### 8.3 Risiken & Einschränkungen
{{GQ_Risiken}}

---

## 9. Versionierung & Änderungsverlauf

### 9.1 Repository / Ablage
{{GQ_Repository}}

### 9.2 Änderungsprotokoll

| Version | Datum | Änderung | Typ (fachlich/technisch) | Autor |
|-------|-------|---------|--------------------------|-------|
| 1.0 | {{GQ_ExportDatum}} | Automatische Erst-Dokumentation | technisch | Auto-Dokumentation |

---

## 10. Freigabe & Review

| Rolle | Name | Datum | Kommentar |
|-----|------|-------|----------|
| Fachlich | {{REVIEW_FachName}} | {{REVIEW_FachDatum}} | {{REVIEW_FachKommentar}} |
| Technisch | {{REVIEW_TechName}} | {{REVIEW_TechDatum}} | {{REVIEW_TechKommentar}} |

---

## 11. Anhänge & Referenzen
- Übergeordnete Workspace-Dokumentation
- Architekturdiagramme
- Regulatorische Nachweise (separat)
"""


def _t(language: str, de: str, en: str) -> str:
    return en if (language or "de").lower().startswith("en") else de


def _manual_hint(language: str) -> str:
    return _t(language, "_Manuell zu ergänzen_", "_To be completed_")


def _none(language: str) -> str:
    return _t(language, "–", "–")


def build_datasources_table(
    data_sources: list[GraphQlDataSourceInfo], language: str = "de"
) -> str:
    """Baut die Tabelle der angebundenen Datenquellen."""
    if not data_sources:
        return _t(
            language, "_Keine Datenquellen verfügbar._", "_No data sources available._"
        )
    header = _t(language, "| Datenquelle | Typ |", "| Data source | Type |")
    dash = _none(language)
    lines = [header, "|---|---|"]
    for ds in data_sources:
        lines.append(
            f"| {_escape_cell(ds.name) or dash} | "
            f"{_escape_cell(ds.source_type) or dash} |"
        )
    return "\n".join(lines)


def build_schema_block(schema: str, language: str = "de") -> str:
    """Baut den (gekürzten) GraphQL-Schema-Codeblock."""
    if not schema:
        return _t(
            language, "_Kein Schema verfügbar._", "_No schema available._"
        )
    text = schema
    if len(text) > _MAX_SCHEMA_CHARS:
        suffix = _t(language, "\n# … (gekürzt)", "\n# … (truncated)")
        text = text[:_MAX_SCHEMA_CHARS] + suffix
    return f"```graphql\n{text}\n```"


def build_service_hint(language: str = "de") -> str:
    return _t(
        language,
        "> **Hinweis:** Datenquellen und Schema werden aus der Definition des "
        "Microsoft Fabric Service (``getDefinition``) gelesen. Fachliche "
        "Beschreibungen sind manuell zu ergänzen.",
        "> **Note:** Data sources and schema are read from the definition of the "
        "Microsoft Fabric service (``getDefinition``). Business descriptions "
        "must be completed manually.",
    )


_MANUAL_PLACEHOLDERS = (
    "KONTAKT_BusinessOwner",
    "KONTAKT_BusinessOwnerMail",
    "KONTAKT_TechOwner",
    "KONTAKT_TechOwnerMail",
    "KONTAKT_DataSteward",
    "KONTAKT_DataStewardMail",
    "KONTAKT_Betrieb",
    "KONTAKT_BetriebMail",
    "GQ_Fachbereich",
    "GQ_Konzerndomaene",
    "GQ_Zielsetzung",
    "GQ_Anwendungsfall",
    "GQ_Konsumenten",
    "GQ_DatenquellenDetail",
    "GQ_ParameterHinweis",
    "GQ_NullHandling",
    "GQ_Validierungsregeln",
    "GQ_Aufbewahrung",
    "GQ_Optimierung",
    "GQ_PerformanceHinweise",
    "GQ_Optimierungen",
    "GQ_Monitoring",
    "GQ_BekannteProbleme",
    "GQ_Zugriffe",
    "GQ_Labels",
    "GQ_Risiken",
    "GQ_Repository",
    "REVIEW_FachName",
    "REVIEW_FachDatum",
    "REVIEW_FachKommentar",
    "REVIEW_TechName",
    "REVIEW_TechDatum",
    "REVIEW_TechKommentar",
)


def build_graphqlapi_values(
    gq: GraphQlApiInfo, export_date: str, language: str = "de"
) -> dict[str, str]:
    """Baut das Platzhalter-Wörterbuch für die GraphQL-API-Vorlage."""
    hint = _manual_hint(language)
    dash = _none(language)

    ds_table = build_datasources_table(gq.data_sources, language)
    values: dict[str, str] = {name: hint for name in _MANUAL_PLACEHOLDERS}
    values.update(
        {
            "GQ_Name": gq.name or dash,
            "GQ_Beschreibung": gq.description or dash,
            "GQ_ID": gq.id or dash,
            "GQ_WebUrl": gq.web_url or dash,
            "GQ_AnzahlDatenquellen": str(len(gq.data_sources)),
            "GQ_ConfiguredBy": gq.configured_by or dash,
            "GQ_ModifiedTime": gq.modified_time or dash,
            "GQ_ExportDatum": export_date,
            "GQ_DatenquellenTabelle": ds_table,
            "GQ_DatenquellenTabelle2": ds_table,
            "GQ_SchemaBlock": build_schema_block(gq.schema, language),
            "GQ_ServiceHinweis": build_service_hint(language),
            "GQ_VerwendungHinweis": _t(
                language,
                "_Die GraphQL-API stellt die angebundenen Datenquellen über einen "
                "GraphQL-Endpunkt bereit. Bitte konkrete Nutzung/Clients fachlich "
                "ergänzen._",
                "_The GraphQL API exposes the connected data sources via a "
                "GraphQL endpoint. Please complete the concrete usage/clients "
                "manually._",
            ),
            "GQ_Beladung": _t(
                language,
                "_Die GraphQL-API liest live aus den angebundenen Datenquellen "
                "(keine eigene Beladung). Bitte Betrieb fachlich ergänzen._",
                "_The GraphQL API reads live from the connected data sources (no "
                "own loading). Please complete operations details manually._",
            ),
        }
    )
    return values


def render_graphqlapi(
    template_content: str,
    gq: GraphQlApiInfo,
    export_date: str,
    language: str = "de",
) -> str:
    """Rendert ein eigenständiges GraphQL-API-Dokument anhand der Vorlage."""
    values = build_graphqlapi_values(gq, export_date, language)
    rendered, _warnings = TemplateRenderer().render(template_content, values)
    return rendered
