"""Generator für die Fabric Copy Job-Dokumentation.

Analog zu :mod:`core.notebook_doc_generator` und
:mod:`core.dataflow_doc_generator`: enthält die eingebaute Standard-Vorlage für
ein eigenständiges Copyjob-Dokument sowie die Funktionen, die aus einem
:class:`~core.models.CopyJobInfo` das Platzhalter-Wörterbuch und die
Markdown-Tabellen/-Abschnitte erzeugen.

Die Vorlage wird – falls noch nicht vorhanden – als Datei neben der Anwendung
erzeugt und danach als Standard verwendet, sodass sie (wie die übrigen
Vorlagen) vom Benutzer angepasst werden kann.
"""
from __future__ import annotations

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

# Dateiname der Standard-Vorlage (liegt neben der EXE / im Projektstamm)
COPYJOB_TEMPLATE_FILENAME = "WorkspaceCopyjobvorlage.md"

__all__ = [
    "COPYJOB_TEMPLATE_FILENAME",
    "DEFAULT_COPYJOB_TEMPLATE",
    "ensure_template",
    "load_template",
    "build_connection_table",
    "build_objects_table",
    "build_activities_section",
    "build_service_hint",
    "build_copyjob_values",
    "render_copyjob",
]


# ---------------------------------------------------------------------------
# Eingebaute Standard-Vorlage (deckungsgleich mit
# PowerBI_Fabric_Copyjob_Dokumentationsvorlage.md im Projektstamm)
# ---------------------------------------------------------------------------

DEFAULT_COPYJOB_TEMPLATE = """# Microsoft Fabric Copy Job-Dokumentation

> **Hinweis:** Diese Dokumentation ist verpflichtend für alle Produktiv-Copyjobs.
> 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 |
|-----|------|
| Copyjob-Name | {{CJ_Name}} |
| Beschreibung | {{CJ_Beschreibung}} |
| Copyjob-ID | {{CJ_ID}} |
| Web-URL | {{CJ_WebUrl}} |
| Job-Modus | {{CJ_JobModus}} |
| Quelle (Typ) | {{CJ_QuelleTyp}} |
| Ziel (Typ) | {{CJ_ZielTyp}} |
| Timeout | {{CJ_Timeout}} |
| Wiederholungen (Retry) | {{CJ_Retry}} |
| Erstellt / konfiguriert von | {{CJ_ConfiguredBy}} |
| Zuletzt geändert | {{CJ_ModifiedTime}} |
| Fachbereich | {{CJ_Fachbereich}} |
| Konzerndomäne | {{CJ_Konzerndomaene}} |
| Aktuelle Version | 1.0 |
| Status | Produktiv |
| Letzte Aktualisierung | {{CJ_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
{{CJ_Zielsetzung}}

### 3.2 Fachlicher Anwendungsfall
{{CJ_Anwendungsfall}}

### 3.3 Nachgelagerte Verbraucher (Pipelines / Berichte / weitere Elemente)
{{CJ_Konsumenten}}

---

## 4. Quelle & Ziel

### 4.1 Verbindungsübersicht

{{CJ_VerbindungsTabelle}}

### 4.2 Kopierverhalten

- Job-Modus: {{CJ_JobModus}}
- Timeout: {{CJ_Timeout}}
- Wiederholungen (Retry): {{CJ_Retry}}

---

## 5. Kopierte Objekte & Abhängigkeiten

### 5.1 Übersicht der kopierten Objekte

{{CJ_ObjekteTabelle}}

### 5.2 Detailbeschreibung je Objekt / Datenquelle
{{CJ_DatenquellenDetail}}

---

## 6. Kopierlogik & Mapping

{{CJ_ServiceHinweis}}

### 6.1 Kopieraufträge je Objekt

{{CJ_Kopierauftraege}}

### 6.2 Parameter & Konfiguration
{{CJ_ParameterHinweis}}

### 6.3 Fehlerbehandlung & Datenqualität

- Umgang mit NULL-/Fehlwerten: {{CJ_NullHandling}}
- Fehlerbehandlung (Retries, Fehlertoleranz): {{CJ_ErrorHandling}}
- Datenvalidierungsregeln: {{CJ_Validierungsregeln}}

### 6.4 Performance-Hinweise

- Staging / Ressourcen: {{CJ_Ressourcen}}
- Bekannte Performance-Engpässe: {{CJ_PerformanceHinweise}}
- Optimierungsmaßnahmen: {{CJ_Optimierungen}}

---

## 7. Betrieb & Wartung

### 7.1 Ausführung & Orchestrierung

{{CJ_Ausfuehrung}}

### 7.2 Monitoring & Fehlerbehandlung
{{CJ_Monitoring}}

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

---

## 8. Sicherheit & Berechtigungen

### 8.1 Zugriff & Freigaben
{{CJ_Zugriffe}}

### 8.2 Sensitivity Labels
{{CJ_Labels}}

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

---

## 9. Versionierung & Änderungsverlauf

### 9.1 Repository / Ablage
{{CJ_Repository}}

### 9.2 Änderungsprotokoll

| Version | Datum | Änderung | Typ (fachlich/technisch) | Autor |
|-------|-------|---------|--------------------------|-------|
| 1.0 | {{CJ_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)
"""


# ---------------------------------------------------------------------------
# Lokalisierungs-Hilfen
# ---------------------------------------------------------------------------

def _t(language: str, de: str, en: str) -> str:
    """Wählt den Text je nach Sprache (Default: Deutsch)."""
    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, "–", "–")


# ---------------------------------------------------------------------------
# Tabellen-/Abschnitts-Generierung
# ---------------------------------------------------------------------------

def build_connection_table(cj: CopyJobInfo, language: str = "de") -> str:
    """Baut die Verbindungsübersicht (Quelle & Ziel)."""
    dash = _none(language)
    header = _t(
        language,
        "| Rolle | Typ | Details |",
        "| Role | Type | Details |",
    )
    source_lbl = _t(language, "Quelle", "Source")
    dest_lbl = _t(language, "Ziel", "Destination")
    lines = [header, "|---|---|---|"]
    lines.append(
        f"| {source_lbl} | {_escape_cell(cj.source_type) or dash} | "
        f"{_escape_cell(cj.source_details) or dash} |"
    )
    lines.append(
        f"| {dest_lbl} | {_escape_cell(cj.destination_type) or dash} | "
        f"{_escape_cell(cj.destination_details) or dash} |"
    )
    return "\n".join(lines)


def build_objects_table(
    activities: list[CopyJobActivityInfo], language: str = "de"
) -> str:
    """Baut die Übersichtstabelle der kopierten Objekte."""
    if not activities:
        return _t(
            language,
            "_Keine kopierten Objekte verfügbar._",
            "_No copied objects available._",
        )
    header = _t(
        language,
        "| # | Quell-Objekt | Ziel-Objekt | Schreibverhalten | Spalten-Mappings |",
        "| # | Source object | Destination object | Write behavior | Column mappings |",
    )
    dash = _none(language)
    lines = [header, "|---|---|---|---|---|"]
    for act in activities:
        lines.append(
            f"| {act.index} | {_escape_cell(act.source_object) or dash} | "
            f"{_escape_cell(act.destination_object) or dash} | "
            f"{_escape_cell(act.write_behavior) or dash} | {len(act.mappings)} |"
        )
    return "\n".join(lines)


def build_activities_section(
    activities: list[CopyJobActivityInfo], language: str = "de"
) -> str:
    """Baut die Detailabschnitte je Kopierauftrag inkl. Spalten-Mapping."""
    if not activities:
        return _t(
            language,
            "_Keine Kopieraufträge verfügbar._",
            "_No copy activities available._",
        )
    dash = _none(language)
    obj_lbl = _t(language, "Objekt", "Object")
    blocks: list[str] = []
    for act in activities:
        title = _escape_cell(act.source_object) or f"{obj_lbl} {act.index}"
        lines = [f"#### {obj_lbl} {act.index}: {title}", ""]
        # Kurzinfos als Aufzählung
        lines.append(
            _t(language, f"- Quelle: {act.source_object or dash}",
               f"- Source: {act.source_object or dash}")
        )
        lines.append(
            _t(language, f"- Ziel: {act.destination_object or dash}",
               f"- Destination: {act.destination_object or dash}")
        )
        if act.write_behavior:
            lines.append(
                _t(language, f"- Schreibverhalten: {act.write_behavior}",
                   f"- Write behavior: {act.write_behavior}")
            )
        if act.table_option:
            lines.append(
                _t(language, f"- Tabellen-Option: {act.table_option}",
                   f"- Table option: {act.table_option}")
            )
        if act.read_method:
            lines.append(
                _t(language, f"- Lesemethode (CDC): {act.read_method}",
                   f"- Read method (CDC): {act.read_method}")
            )
        # Mapping-Tabelle
        if act.mappings:
            lines.append("")
            lines.append(
                _t(language,
                   "| Quell-Spalte | Quell-Typ | Ziel-Spalte | Ziel-Typ |",
                   "| Source column | Source type | Destination column | Destination type |")
            )
            lines.append("|---|---|---|---|")
            for m in act.mappings:
                lines.append(
                    f"| {_escape_cell(m.source_name) or dash} | "
                    f"{_escape_cell(m.source_type) or dash} | "
                    f"{_escape_cell(m.destination_name) or dash} | "
                    f"{_escape_cell(m.destination_type) or dash} |"
                )
        else:
            lines.append("")
            lines.append(
                _t(language,
                   "_Kein explizites Spalten-Mapping (1:1-Übernahme)._",
                   "_No explicit column mapping (1:1 copy)._")
            )
        blocks.append("\n".join(lines))
    return "\n\n".join(blocks)


def build_service_hint(language: str = "de") -> str:
    """Baut den Hinweis zur Datenherkunft/Extraktion."""
    return _t(
        language,
        "> **Hinweis:** Die Kopierlogik wird aus der Copyjob-Definition "
        "(`getDefinition` → `copyjob-content.json`) des Microsoft Fabric Service "
        "gelesen. Ist der Export nicht verfügbar, bleiben die Detailabschnitte "
        "leer.",
        "> **Note:** The copy logic is read from the copy job definition "
        "(`getDefinition` → `copyjob-content.json`) of the Microsoft Fabric "
        "service. If the export is unavailable, the detail sections remain "
        "empty.",
    )


# ---------------------------------------------------------------------------
# Platzhalter-Werte & Rendering
# ---------------------------------------------------------------------------

_MANUAL_PLACEHOLDERS = (
    "KONTAKT_BusinessOwner",
    "KONTAKT_BusinessOwnerMail",
    "KONTAKT_TechOwner",
    "KONTAKT_TechOwnerMail",
    "KONTAKT_DataSteward",
    "KONTAKT_DataStewardMail",
    "KONTAKT_Betrieb",
    "KONTAKT_BetriebMail",
    "CJ_Fachbereich",
    "CJ_Konzerndomaene",
    "CJ_Zielsetzung",
    "CJ_Anwendungsfall",
    "CJ_Konsumenten",
    "CJ_DatenquellenDetail",
    "CJ_ParameterHinweis",
    "CJ_NullHandling",
    "CJ_ErrorHandling",
    "CJ_Validierungsregeln",
    "CJ_Ressourcen",
    "CJ_PerformanceHinweise",
    "CJ_Optimierungen",
    "CJ_Monitoring",
    "CJ_BekannteProbleme",
    "CJ_Zugriffe",
    "CJ_Labels",
    "CJ_Risiken",
    "CJ_Repository",
    "REVIEW_FachName",
    "REVIEW_FachDatum",
    "REVIEW_FachKommentar",
    "REVIEW_TechName",
    "REVIEW_TechDatum",
    "REVIEW_TechKommentar",
)


def build_copyjob_values(
    cj: CopyJobInfo, export_date: str, language: str = "de"
) -> dict[str, str]:
    """Baut das Platzhalter-Wörterbuch für die Copyjob-Vorlage."""
    hint = _manual_hint(language)
    dash = _none(language)

    values: dict[str, str] = {name: hint for name in _MANUAL_PLACEHOLDERS}
    values.update(
        {
            "CJ_Name": cj.name or dash,
            "CJ_Beschreibung": cj.description or dash,
            "CJ_ID": cj.id or dash,
            "CJ_WebUrl": cj.web_url or dash,
            "CJ_JobModus": cj.job_mode or dash,
            "CJ_QuelleTyp": cj.source_type or dash,
            "CJ_ZielTyp": cj.destination_type or dash,
            "CJ_Timeout": cj.timeout or dash,
            "CJ_Retry": cj.retry or dash,
            "CJ_ConfiguredBy": cj.configured_by or dash,
            "CJ_ModifiedTime": cj.modified_time or dash,
            "CJ_ExportDatum": export_date,
            "CJ_VerbindungsTabelle": build_connection_table(cj, language),
            "CJ_ObjekteTabelle": build_objects_table(cj.activities, language),
            "CJ_Kopierauftraege": build_activities_section(cj.activities, language),
            "CJ_ServiceHinweis": build_service_hint(language),
            "CJ_Ausfuehrung": _t(
                language,
                "_Copyjobs werden i. d. R. manuell, über einen Zeitplan oder "
                "über Data-Pipelines ausgeführt. Bitte Orchestrierung/Trigger "
                "fachlich ergänzen._",
                "_Copy jobs are typically run manually, on a schedule, or via "
                "data pipelines. Please complete the orchestration/trigger "
                "details._",
            ),
        }
    )
    return values


def render_copyjob(
    template_content: str,
    cj: CopyJobInfo,
    export_date: str,
    language: str = "de",
) -> str:
    """Rendert ein eigenständiges Copyjob-Dokument anhand der Vorlage."""
    values = build_copyjob_values(cj, export_date, language)
    rendered, _warnings = TemplateRenderer().render(template_content, values)
    return rendered
