"""Generator für die Fabric Data Pipeline-Dokumentation.

Analog zu :mod:`core.copyjob_doc_generator`: eingebaute Standard-Vorlage +
Rendering aus einem :class:`~core.models.DataPipelineInfo`. Data Pipelines
werden über ``getDefinition`` → ``pipeline-content.json`` gelesen und über ihre
Aktivitäten, Abhängigkeiten, Parameter und Variablen dokumentiert.
"""
from __future__ import annotations

from core.models import (
    DataPipelineActivityInfo,
    DataPipelineInfo,
    DataPipelineParameterInfo,
)
from core.template_renderer import TemplateRenderer
from core.workspace_doc_generator import _escape_cell, ensure_template, load_template

PIPELINE_TEMPLATE_FILENAME = "WorkspacePipelinevorlage.md"

__all__ = [
    "PIPELINE_TEMPLATE_FILENAME",
    "DEFAULT_PIPELINE_TEMPLATE",
    "ensure_template",
    "load_template",
    "build_activities_table",
    "build_dependencies_section",
    "build_parameters_table",
    "build_service_hint",
    "build_pipeline_values",
    "render_pipeline",
]


DEFAULT_PIPELINE_TEMPLATE = """# Microsoft Fabric Data Pipeline-Dokumentation

> **Hinweis:** Diese Dokumentation ist verpflichtend für alle Produktiv-Pipelines.
> 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 |
|-----|------|
| Pipeline-Name | {{PL_Name}} |
| Beschreibung | {{PL_Beschreibung}} |
| Pipeline-ID | {{PL_ID}} |
| Web-URL | {{PL_WebUrl}} |
| Anzahl Aktivitäten | {{PL_AnzahlAktivitaeten}} |
| Erstellt / konfiguriert von | {{PL_ConfiguredBy}} |
| Zuletzt geändert | {{PL_ModifiedTime}} |
| Fachbereich | {{PL_Fachbereich}} |
| Konzerndomäne | {{PL_Konzerndomaene}} |
| Aktuelle Version | 1.0 |
| Status | Produktiv |
| Letzte Aktualisierung | {{PL_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
{{PL_Zielsetzung}}

### 3.2 Fachlicher Anwendungsfall
{{PL_Anwendungsfall}}

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

---

## 4. Aufbau & Ablauf

### 4.1 Übersicht der Aktivitäten

{{PL_AktivitaetenTabelle}}

### 4.2 Abhängigkeiten (Ausführungsreihenfolge)

{{PL_AbhaengigkeitenAbschnitt}}

---

## 5. Datenquellen & Ziele

### 5.1 Beteiligte Datenquellen / Ziele

{{PL_DatenquellenTabelle}}

### 5.2 Detailbeschreibung je Datenquelle
{{PL_DatenquellenDetail}}

---

## 6. Logik & Konfiguration

{{PL_ServiceHinweis}}

### 6.1 Parameter

{{PL_ParameterTabelle}}

### 6.2 Variablen

{{PL_VariablenTabelle}}

### 6.3 Fehlerbehandlung & Datenqualität

- Umgang mit Fehlern (Retry, On-Fail): {{PL_ErrorHandling}}
- Datenvalidierungsregeln: {{PL_Validierungsregeln}}
- Idempotenz / Wiederanlauf: {{PL_Idempotenz}}

### 6.4 Performance-Hinweise

- Parallelität / Batching: {{PL_Parallelitaet}}
- Bekannte Performance-Engpässe: {{PL_PerformanceHinweise}}
- Optimierungsmaßnahmen: {{PL_Optimierungen}}

---

## 7. Betrieb & Wartung

### 7.1 Ausführung & Orchestrierung (Trigger / Zeitplan)

{{PL_Ausfuehrung}}

### 7.2 Monitoring & Fehlerbehandlung
{{PL_Monitoring}}

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

---

## 8. Sicherheit & Berechtigungen

### 8.1 Zugriff & Freigaben
{{PL_Zugriffe}}

### 8.2 Sensitivity Labels
{{PL_Labels}}

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

---

## 9. Versionierung & Änderungsverlauf

### 9.1 Repository / Ablage
{{PL_Repository}}

### 9.2 Änderungsprotokoll

| Version | Datum | Änderung | Typ (fachlich/technisch) | Autor |
|-------|-------|---------|--------------------------|-------|
| 1.0 | {{PL_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_activities_table(
    activities: list[DataPipelineActivityInfo], language: str = "de"
) -> str:
    """Baut die Übersichtstabelle der Aktivitäten."""
    if not activities:
        return _t(
            language,
            "_Keine Aktivitäten verfügbar._",
            "_No activities available._",
        )
    header = _t(
        language,
        "| # | Aktivität | Typ | Enthalten in | Abhängig von |",
        "| # | Activity | Type | Contained in | Depends on |",
    )
    dash = _none(language)
    lines = [header, "|---|---|---|---|---|"]
    for idx, act in enumerate(activities, start=1):
        depends = ", ".join(act.depends_on) if act.depends_on else dash
        lines.append(
            f"| {idx} | {_escape_cell(act.name)} | "
            f"{_escape_cell(act.activity_type) or dash} | "
            f"{_escape_cell(act.container) or dash} | {_escape_cell(depends)} |"
        )
    return "\n".join(lines)


def build_dependencies_section(
    activities: list[DataPipelineActivityInfo], language: str = "de"
) -> str:
    """Baut eine textuelle Darstellung der Ausführungsabhängigkeiten."""
    dep_lines: list[str] = []
    for act in activities:
        if act.depends_on:
            joined = ", ".join(act.depends_on)
            dep_lines.append(
                _t(
                    language,
                    f"- **{act.name}** läuft nach: {joined}",
                    f"- **{act.name}** runs after: {joined}",
                )
            )
    if not dep_lines:
        return _t(
            language,
            "_Keine expliziten Abhängigkeiten – Aktivitäten starten parallel bzw. "
            "eigenständig._",
            "_No explicit dependencies – activities start in parallel or "
            "independently._",
        )
    return "\n".join(dep_lines)


def build_parameters_table(
    params: list[DataPipelineParameterInfo], language: str = "de", *, is_variable: bool = False
) -> str:
    """Baut die Parameter-/Variablen-Tabelle."""
    if not params:
        return _t(
            language,
            "_Keine Variablen definiert._" if is_variable else "_Keine Parameter definiert._",
            "_No variables defined._" if is_variable else "_No parameters defined._",
        )
    name_lbl = _t(language, "Variable", "Variable") if is_variable else _t(
        language, "Parameter", "Parameter"
    )
    header = _t(
        language,
        f"| {name_lbl} | Typ | Standardwert |",
        f"| {name_lbl} | Type | Default value |",
    )
    dash = _none(language)
    lines = [header, "|---|---|---|"]
    for p in params:
        lines.append(
            f"| {_escape_cell(p.name)} | {_escape_cell(p.param_type) or dash} | "
            f"{_escape_cell(p.default_value) or dash} |"
        )
    return "\n".join(lines)


def build_service_hint(language: str = "de") -> str:
    return _t(
        language,
        "> **Hinweis:** Aktivitäten, Abhängigkeiten, Parameter und Variablen "
        "werden aus der Pipeline-Definition (`getDefinition` → "
        "`pipeline-content.json`) des Microsoft Fabric Service gelesen. Ist der "
        "Export nicht verfügbar, bleiben die Abschnitte leer.",
        "> **Note:** Activities, dependencies, parameters and variables are read "
        "from the pipeline definition (`getDefinition` → `pipeline-content.json`) "
        "of the Microsoft Fabric service. If the export is unavailable, the "
        "sections remain empty.",
    )


_MANUAL_PLACEHOLDERS = (
    "KONTAKT_BusinessOwner",
    "KONTAKT_BusinessOwnerMail",
    "KONTAKT_TechOwner",
    "KONTAKT_TechOwnerMail",
    "KONTAKT_DataSteward",
    "KONTAKT_DataStewardMail",
    "KONTAKT_Betrieb",
    "KONTAKT_BetriebMail",
    "PL_Fachbereich",
    "PL_Konzerndomaene",
    "PL_Zielsetzung",
    "PL_Anwendungsfall",
    "PL_Konsumenten",
    "PL_DatenquellenDetail",
    "PL_ErrorHandling",
    "PL_Validierungsregeln",
    "PL_Idempotenz",
    "PL_Parallelitaet",
    "PL_PerformanceHinweise",
    "PL_Optimierungen",
    "PL_Monitoring",
    "PL_BekannteProbleme",
    "PL_Zugriffe",
    "PL_Labels",
    "PL_Risiken",
    "PL_Repository",
    "REVIEW_FachName",
    "REVIEW_FachDatum",
    "REVIEW_FachKommentar",
    "REVIEW_TechName",
    "REVIEW_TechDatum",
    "REVIEW_TechKommentar",
)


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

    values: dict[str, str] = {name: hint for name in _MANUAL_PLACEHOLDERS}
    values.update(
        {
            "PL_Name": pl.name or dash,
            "PL_Beschreibung": pl.description or dash,
            "PL_ID": pl.id or dash,
            "PL_WebUrl": pl.web_url or dash,
            "PL_AnzahlAktivitaeten": str(len(pl.activities)),
            "PL_ConfiguredBy": pl.configured_by or dash,
            "PL_ModifiedTime": pl.modified_time or dash,
            "PL_ExportDatum": export_date,
            "PL_AktivitaetenTabelle": build_activities_table(pl.activities, language),
            "PL_AbhaengigkeitenAbschnitt": build_dependencies_section(
                pl.activities, language
            ),
            "PL_ParameterTabelle": build_parameters_table(pl.parameters, language),
            "PL_VariablenTabelle": build_parameters_table(
                pl.variables, language, is_variable=True
            ),
            "PL_ServiceHinweis": build_service_hint(language),
            "PL_DatenquellenTabelle": _t(
                language,
                "_Beteiligte Datenquellen/Ziele werden aus den Aktivitäten "
                "abgeleitet (siehe Abschnitt 4). Bitte fachlich ergänzen._",
                "_Involved data sources/destinations are derived from the "
                "activities (see section 4). Please complete manually._",
            ),
            "PL_Ausfuehrung": _t(
                language,
                "_Pipelines werden über Zeitpläne, Trigger oder übergeordnete "
                "Pipelines ausgeführt. Bitte Orchestrierung/Trigger fachlich "
                "ergänzen._",
                "_Pipelines are executed via schedules, triggers or parent "
                "pipelines. Please complete the orchestration/trigger details._",
            ),
        }
    )
    return values


def render_pipeline(
    template_content: str,
    pl: DataPipelineInfo,
    export_date: str,
    language: str = "de",
) -> str:
    """Rendert ein eigenständiges Pipeline-Dokument anhand der Vorlage."""
    values = build_pipeline_values(pl, export_date, language)
    rendered, _warnings = TemplateRenderer().render(template_content, values)
    return rendered
