"""Generator für die Fabric Spark-Job-Definition-Dokumentation.

Definition-basiert (analog zu :mod:`core.copyjob_doc_generator`): die
``SparkJobDefinitionV1.json`` beschreibt ausführbare Datei, Sprache,
Hauptklasse, Argumente und Bibliotheken. Rendering aus einem
:class:`~core.models.SparkJobDefinitionInfo`.
"""
from __future__ import annotations

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

SPARKJOB_TEMPLATE_FILENAME = "WorkspaceSparkJobDefinitionvorlage.md"

__all__ = [
    "SPARKJOB_TEMPLATE_FILENAME",
    "DEFAULT_SPARKJOB_TEMPLATE",
    "ensure_template",
    "load_template",
    "build_config_section",
    "build_libraries_table",
    "build_service_hint",
    "build_sparkjob_values",
    "render_sparkjob",
]


DEFAULT_SPARKJOB_TEMPLATE = """# Microsoft Fabric Spark-Job-Definition-Dokumentation

> **Hinweis:** Diese Dokumentation ist verpflichtend für alle Produktiv-Spark-Job-Definitionen.
> 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 |
|-----|------|
| Spark-Job-Definition-Name | {{SJ_Name}} |
| Beschreibung | {{SJ_Beschreibung}} |
| Spark-Job-Definition-ID | {{SJ_ID}} |
| Web-URL | {{SJ_WebUrl}} |
| Sprache | {{SJ_Language}} |
| Ausführbare Datei | {{SJ_ExecutableFile}} |
| Hauptklasse | {{SJ_MainClass}} |
| Standard-Lakehouse | {{SJ_DefaultLakehouse}} |
| Erstellt / konfiguriert von | {{SJ_ConfiguredBy}} |
| Zuletzt geändert | {{SJ_ModifiedTime}} |
| Fachbereich | {{SJ_Fachbereich}} |
| Konzerndomäne | {{SJ_Konzerndomaene}} |
| Aktuelle Version | 1.0 |
| Status | Produktiv |
| Letzte Aktualisierung | {{SJ_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
{{SJ_Zielsetzung}}

### 3.2 Fachlicher Anwendungsfall
{{SJ_Anwendungsfall}}

### 3.3 Nachgelagerte Verbraucher (Pipelines / Lakehouses)
{{SJ_Konsumenten}}

---

## 4. Aufbau & Konfiguration

### 4.1 Ausführungskonfiguration

{{SJ_KonfigTabelle}}

### 4.2 Zusätzliche Bibliotheken

{{SJ_BibliothekenTabelle}}

---

## 5. Datenquellen & Beladung

### 5.1 Datenquellen / verarbeitete Objekte

{{SJ_DatenquellenTabelle}}

### 5.2 Detailbeschreibung je Datenquelle
{{SJ_DatenquellenDetail}}

---

## 6. Inhalt & Nutzung

{{SJ_ServiceHinweis}}

### 6.1 Ausführungslogik
{{SJ_LogikHinweis}}

### 6.2 Parameter & Argumente
{{SJ_ParameterHinweis}}

### 6.3 Datenqualität

- Umgang mit Fehlern: {{SJ_NullHandling}}
- Datenvalidierungsregeln: {{SJ_Validierungsregeln}}
- Aufbewahrung / Historisierung: {{SJ_Aufbewahrung}}

### 6.4 Performance-Hinweise

- Ressourcen / Optimierung: {{SJ_Optimierung}}
- Bekannte Performance-Engpässe: {{SJ_PerformanceHinweise}}
- Weitere Maßnahmen: {{SJ_Optimierungen}}

---

## 7. Betrieb & Wartung

### 7.1 Ausführung & Orchestrierung

{{SJ_Beladung}}

### 7.2 Monitoring & Fehlerbehandlung
{{SJ_Monitoring}}

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

---

## 8. Sicherheit & Berechtigungen

### 8.1 Zugriff & Freigaben
{{SJ_Zugriffe}}

### 8.2 Sensitivity Labels
{{SJ_Labels}}

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

---

## 9. Versionierung & Änderungsverlauf

### 9.1 Repository / Ablage
{{SJ_Repository}}

### 9.2 Änderungsprotokoll

| Version | Datum | Änderung | Typ (fachlich/technisch) | Autor |
|-------|-------|---------|--------------------------|-------|
| 1.0 | {{SJ_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_config_section(sj: SparkJobDefinitionInfo, language: str = "de") -> str:
    """Baut die Tabelle mit der Ausführungskonfiguration."""
    dash = _none(language)
    header = _t(language, "| Eigenschaft | Wert |", "| Property | Value |")
    lang_lbl = _t(language, "Sprache", "Language")
    exec_lbl = _t(language, "Ausführbare Datei", "Executable file")
    main_lbl = _t(language, "Hauptklasse", "Main class")
    lh_lbl = _t(language, "Standard-Lakehouse", "Default lakehouse")
    args_lbl = _t(language, "Argumente", "Arguments")
    lines = [
        header,
        "|---|---|",
        f"| {lang_lbl} | {_escape_cell(sj.language) or dash} |",
        f"| {exec_lbl} | {_escape_cell(sj.executable_file) or dash} |",
        f"| {main_lbl} | {_escape_cell(sj.main_class) or dash} |",
        f"| {lh_lbl} | {_escape_cell(sj.default_lakehouse) or dash} |",
        f"| {args_lbl} | {_escape_cell(sj.command_line_arguments) or dash} |",
    ]
    return "\n".join(lines)


def build_libraries_table(libraries: list[str], language: str = "de") -> str:
    """Baut die Tabelle der zusätzlichen Bibliotheken."""
    if not libraries:
        return _t(
            language,
            "_Keine zusätzlichen Bibliotheken angegeben._",
            "_No additional libraries specified._",
        )
    header = _t(language, "| Bibliothek |", "| Library |")
    dash = _none(language)
    lines = [header, "|---|"]
    for lib in libraries:
        lines.append(f"| {_escape_cell(lib) or dash} |")
    return "\n".join(lines)


def build_service_hint(language: str = "de") -> str:
    return _t(
        language,
        "> **Hinweis:** Die Konfiguration wird aus der Definition "
        "(`SparkJobDefinitionV1.json`) des Microsoft Fabric Service gelesen. "
        "Fachliche Beschreibungen sind manuell zu ergänzen.",
        "> **Note:** The configuration is read from the definition "
        "(`SparkJobDefinitionV1.json`) of the Microsoft Fabric service. "
        "Business descriptions must be completed manually.",
    )


_MANUAL_PLACEHOLDERS = (
    "KONTAKT_BusinessOwner",
    "KONTAKT_BusinessOwnerMail",
    "KONTAKT_TechOwner",
    "KONTAKT_TechOwnerMail",
    "KONTAKT_DataSteward",
    "KONTAKT_DataStewardMail",
    "KONTAKT_Betrieb",
    "KONTAKT_BetriebMail",
    "SJ_Fachbereich",
    "SJ_Konzerndomaene",
    "SJ_Zielsetzung",
    "SJ_Anwendungsfall",
    "SJ_Konsumenten",
    "SJ_DatenquellenTabelle",
    "SJ_DatenquellenDetail",
    "SJ_ParameterHinweis",
    "SJ_NullHandling",
    "SJ_Validierungsregeln",
    "SJ_Aufbewahrung",
    "SJ_Optimierung",
    "SJ_PerformanceHinweise",
    "SJ_Optimierungen",
    "SJ_Monitoring",
    "SJ_BekannteProbleme",
    "SJ_Zugriffe",
    "SJ_Labels",
    "SJ_Risiken",
    "SJ_Repository",
    "REVIEW_FachName",
    "REVIEW_FachDatum",
    "REVIEW_FachKommentar",
    "REVIEW_TechName",
    "REVIEW_TechDatum",
    "REVIEW_TechKommentar",
)


def build_sparkjob_values(
    sj: SparkJobDefinitionInfo, export_date: str, language: str = "de"
) -> dict[str, str]:
    """Baut das Platzhalter-Wörterbuch für die Spark-Job-Definition-Vorlage."""
    hint = _manual_hint(language)
    dash = _none(language)

    values: dict[str, str] = {name: hint for name in _MANUAL_PLACEHOLDERS}
    values.update(
        {
            "SJ_Name": sj.name or dash,
            "SJ_Beschreibung": sj.description or dash,
            "SJ_ID": sj.id or dash,
            "SJ_WebUrl": sj.web_url or dash,
            "SJ_Language": sj.language or dash,
            "SJ_ExecutableFile": sj.executable_file or dash,
            "SJ_MainClass": sj.main_class or dash,
            "SJ_DefaultLakehouse": sj.default_lakehouse or dash,
            "SJ_ConfiguredBy": sj.configured_by or dash,
            "SJ_ModifiedTime": sj.modified_time or dash,
            "SJ_ExportDatum": export_date,
            "SJ_KonfigTabelle": build_config_section(sj, language),
            "SJ_BibliothekenTabelle": build_libraries_table(
                sj.additional_libraries, language
            ),
            "SJ_ServiceHinweis": build_service_hint(language),
            "SJ_LogikHinweis": _t(
                language,
                "_Die Spark Job Definition führt den angegebenen Code (Datei/"
                "Hauptklasse) auf dem Spark-Cluster aus. Bitte konkrete "
                "Ausführungslogik fachlich ergänzen._",
                "_The Spark job definition runs the specified code (file/main "
                "class) on the Spark cluster. Please complete the concrete "
                "execution logic manually._",
            ),
            "SJ_Beladung": _t(
                language,
                "_Spark Job Definitions werden manuell oder über Pipelines "
                "ausgeführt. Bitte Orchestrierung fachlich ergänzen._",
                "_Spark job definitions are run manually or via pipelines. "
                "Please complete the orchestration details manually._",
            ),
        }
    )
    return values


def render_sparkjob(
    template_content: str,
    sj: SparkJobDefinitionInfo,
    export_date: str,
    language: str = "de",
) -> str:
    """Rendert ein eigenständiges Spark-Job-Definition-Dokument anhand der Vorlage."""
    values = build_sparkjob_values(sj, export_date, language)
    rendered, _warnings = TemplateRenderer().render(template_content, values)
    return rendered
