"""Formular-Generator für die PBI Documentation by Oliver Gropp.

Logik-Schicht für die Formular-Generierung: bereitet Datenstrukturen
für das GUI vor, erstellt aber keine tkinter-Widgets direkt.
"""
from __future__ import annotations

import re
from dataclasses import dataclass, field

from core.models import PlaceholderMapping


@dataclass
class FormField:
    """Ein einzelnes Formularfeld."""
    placeholder_name: str
    label: str
    context: str
    current_value: str
    is_auto_filled: bool
    is_required: bool


@dataclass
class FormSection:
    """Eine Gruppe von Formularfeldern, gruppiert nach Kapitel."""
    section_name: str
    fields: list[FormField] = field(default_factory=list)


@dataclass
class ValidationMessage:
    """Eine Validierungsmeldung für ein Formularfeld."""
    field_name: str
    message: str


class FormGenerator:
    """Erzeugt Formulardaten aus Platzhalter-Zuordnungen.

    Dies ist die Logik-Schicht: sie bereitet die Datenstruktur für das
    GUI vor, erstellt aber keine tkinter-Widgets direkt.
    """

    # Englische Übersetzung der Platzhalter-Labelnamen
    _LABELS_EN: dict[str, str] = {
        "ReportName": "Report Name",
        "Kurzbeschreibung": "Description",
        "Fachbereich": "Business Unit",
        "Abteilung": "Department",
        "Konzerndomäne": "Corporate Domain",
        "ProduktivDatum": "In Production Since",
        "BusinessOwner": "Business Owner",
        "BusinessOwnerMail": "Business Owner Email",
        "TechOwner": "Technical Owner",
        "TechOwnerMail": "Technical Owner Email",
        "DataOwner": "Data Owner",
        "DataSteward": "Data Steward",
        "DataStewardMail": "Data Steward Email",
        "Betrieb": "Operations / Support",
        "BetriebMail": "Operations Email",
        "Zielsetzung": "Objective",
        "Anwendungsfall": "Use Case",
        "Abhängigkeiten": "Dependencies",
        "Name": "Name",
        "Beschreibung": "Description",
        "Definition": "Definition",
        "Berechnungslogik": "Calculation Logic",
        "Begriff": "Term",
        "Quelle": "Source",
        "System": "System",
        "SchemaTabellen": "Schema / Tables",
        "Owner": "Owner",
        "Domäne": "Domain",
        "Detailbeschreibung": "Detailed Description",
        "Architektur": "Architecture",
        "PipelineReferenz": "Pipeline Reference",
        "Lineage": "Lineage",
        "ServiceHinweis": "Service Note",
        "ZielTabelle": "Target Table",
        "Schrittname": "Step Name",
        "MCode": "M-Code",
        "Standardwert": "Default Value",
        "Spalte": "Column",
        "QuellTyp": "Source Data Type",
        "ZielTyp": "Target Data Type",
        "Transformation": "Transformation",
        "NullHandling": "NULL Handling",
        "ErrorHandling": "Error Handling",
        "Validierungsregeln": "Validation Rules",
        "QueryFolding": "Query Folding",
        "PerformanceHinweise": "Performance Notes",
        "Optimierungen": "Optimizations",
        "DatasetName": "Dataset Name",
        "BerichtName": "Report Name",
        "AppName": "App Name",
        "BerichtID": "Report ID",
        "BerichtURL": "Report URL",
        "Tabelle": "Table",
        "Typ": "Type",
        "Von": "From",
        "Nach": "To",
        "Kardinalität": "Cardinality",
        "Kreuzfilter": "Cross Filter",
        "Aktiv": "Active",
        "Measure": "Measure",
        "Formel": "Formula",
        "CalcBeschreibung": "Calc Description",
        "Visuals": "Visuals",
        "Rolle": "Role",
        "FilterLogik": "Filter Logic",
        "RLSBeschreibung": "RLS Description",
        "OLSBeschreibung": "OLS Description",
        "Labels": "Labels",
        "Risiken": "Risks",
        "Frequenz": "Frequency",
        "Uhrzeit": "Time",
        "Jobs": "Dependencies",
        "Monitoring": "Monitoring",
        "BekannteProbleme": "Known Issues",
        "Analyse": "Analysis",
        "Repository": "Repository",
        "Version": "Version",
        "Datum": "Date",
        "Änderung": "Change",
        "AlterWert": "Old Value",
        "NeuerWert": "New Value",
        "Autor": "Author",
        "FachName": "Business Reviewer",
        "FachDatum": "Business Review Date",
        "FachKommentar": "Business Comment",
        "TechName": "Technical Reviewer",
        "TechDatum": "Technical Review Date",
        "TechKommentar": "Technical Comment",
    }

    def __init__(self, locale: str = "de") -> None:
        """Initialisiert den FormGenerator.

        Args:
            locale: Sprache für die Label-Generierung ("de" oder "en").
        """
        self._locale = locale

    @staticmethod
    def _clean_label(name: str, locale: str = "de") -> str:
        """Erzeugt ein lesbares Label aus einem Platzhalter-Namen.

        Entfernt Kapitel-Präfixe (META_, KONTAKT_, DS_, PQ_, etc.),
        fügt Leerzeichen vor Großbuchstaben ein und bereinigt
        Unterstriche/Bindestriche.

        Bei locale="en" wird versucht, eine englische Übersetzung
        aus der Label-Map zu verwenden.
        """
        # Präfix vor dem ersten Unterstrich entfernen
        rest = name
        if "_" in name:
            prefix, rest = name.split("_", 1)
            # Nur entfernen wenn der Präfix komplett uppercase ist (META, DS, PQ, etc.)
            if not (prefix.isupper() or prefix in (
                "META", "KONTAKT", "BIZ", "KPI", "GLOSSAR", "DS", "PQ",
                "PQT", "PARAM", "COL", "MODELL", "DAX", "RLS", "SEC",
                "REFRESH", "OPS", "VER", "LOG", "REVIEW", "DEP",
                "ENDORSEMENT", "TBLTYP",
            )):
                rest = name

        # Englische Übersetzung verwenden, falls verfügbar
        if locale == "en" and rest in FormGenerator._LABELS_EN:
            return FormGenerator._LABELS_EN[rest]

        # Replace underscores and hyphens with spaces
        label = rest.replace("_", " ").replace("-", " ")
        # Insert space before uppercase letters (CamelCase → Camel Case)
        label = re.sub(r"(?<=[a-z])(?=[A-Z])", " ", label)
        return label.strip()

    def generate_form_data(
        self, mappings: list[PlaceholderMapping]
    ) -> list[FormSection]:
        """Erzeugt Formulardaten aus Platzhalter-Zuordnungen.

        Gruppiert PlaceholderMappings nach dem Kapitel (section) des
        Platzhalters und erzeugt für jede Sektion eine FormSection
        mit den entsprechenden FormField-Objekten.

        Args:
            mappings: Liste von PlaceholderMapping-Objekten.

        Returns:
            Liste von FormSection-Objekten, gruppiert nach Kapitel.
        """
        # Group by section, preserving order of first appearance
        seen_sections: dict[str, list[PlaceholderMapping]] = {}
        for mapping in mappings:
            section = mapping.placeholder.section or ""
            if section not in seen_sections:
                seen_sections[section] = []
            seen_sections[section].append(mapping)

        sections: list[FormSection] = []
        for section_name, section_mappings in seen_sections.items():
            fields: list[FormField] = []
            for m in section_mappings:
                fields.append(
                    FormField(
                        placeholder_name=m.placeholder.name,
                        label=self._clean_label(m.placeholder.name, self._locale),
                        context=m.placeholder.context,
                        current_value=m.value if m.value is not None else "",
                        is_auto_filled=m.source == "auto",
                        is_required=True,
                    )
                )
            sections.append(FormSection(section_name=section_name, fields=fields))

        return sections

    def validate(
        self,
        form_data: dict[str, str],
        required_fields: list[str] | None = None,
    ) -> list[ValidationMessage]:
        """Validiert Formulareingaben.

        Prüft, ob alle Pflichtfelder einen nicht-leeren Wert haben.

        Args:
            form_data: Dictionary mit Feldname → Wert.
            required_fields: Optionale Liste von Pflichtfeld-Namen.
                Falls None, werden alle Felder in form_data geprüft.

        Returns:
            Liste von ValidationMessage-Objekten. Leere Liste = alles gültig.
        """
        fields_to_check = required_fields if required_fields is not None else list(form_data.keys())
        messages: list[ValidationMessage] = []
        for field_name in fields_to_check:
            value = form_data.get(field_name, "")
            if not value or not value.strip():
                if self._locale == "en":
                    msg = f"Required field '{field_name}' is empty."
                else:
                    msg = f"Pflichtfeld '{field_name}' ist nicht befüllt."
                messages.append(
                    ValidationMessage(
                        field_name=field_name,
                        message=msg,
                    )
                )
        return messages

    def merge_values(
        self,
        auto_values: dict[str, str],
        manual_values: dict[str, str],
    ) -> dict[str, str]:
        """Führt automatisch und manuell befüllte Werte zusammen.

        Manuelle Werte überschreiben automatische Werte.

        Args:
            auto_values: Automatisch befüllte Werte.
            manual_values: Manuell eingegebene Werte.

        Returns:
            Zusammengeführtes Dictionary.
        """
        merged = dict(auto_values)
        merged.update(manual_values)
        return merged
