"""Datenmodelle für die PBI Documentation by Oliver Gropp.

Enthält alle Dataclasses für Metadaten, Template-Parsing,
Verbindungskonfiguration, Versionierung und Fehlerklassen.
"""
from __future__ import annotations

from dataclasses import dataclass, field


# ---------------------------------------------------------------------------
# Report-Metadaten Datenklassen
# ---------------------------------------------------------------------------

@dataclass
class ColumnInfo:
    """Informationen zu einer Spalte in einer Power BI Tabelle."""
    name: str
    table_name: str
    data_type: str
    description: str
    is_hidden: bool
    is_calculated: bool
    expression: str | None = None
    synonyms: list[str] = field(default_factory=list)
    is_key: bool = False


@dataclass
class TableInfo:
    """Informationen zu einer Power BI Tabelle."""
    name: str
    description: str
    columns: list[ColumnInfo] = field(default_factory=list)
    is_hidden: bool = False
    row_count: int | None = None
    mode: str = ""  # "import", "directQuery", "dual", "calculated"
    table_type: str = ""  # "Faktentabelle", "Dimensionstabelle", "Hilfstabelle"


@dataclass
class MeasureInfo:
    """Informationen zu einem DAX Measure."""
    name: str
    table_name: str
    expression: str
    description: str
    format_string: str | None = None


@dataclass
class RelationshipInfo:
    """Informationen zu einer Beziehung zwischen Tabellen."""
    from_table: str
    from_column: str
    to_table: str
    to_column: str
    cardinality: str  # "OneToMany", "ManyToOne", etc.
    cross_filter: str  # "Single", "Both"
    is_active: bool


@dataclass
class DataSourceInfo:
    """Informationen zu einer Datenquelle."""
    name: str
    source_type: str  # "SQL", "OData", "SharePoint", etc.
    connection_string: str
    schema: str | None = None
    tables: list[str] = field(default_factory=list)


@dataclass
class PowerQueryInfo:
    """Informationen zu einer Power Query Abfrage."""
    name: str
    source: str
    target_table: str
    m_expression: str
    description: str


@dataclass
class RLSRoleInfo:
    """Informationen zu einer Row-Level Security Rolle."""
    name: str
    description: str
    filter_expressions: dict[str, str] = field(default_factory=dict)
    members: list[str] = field(default_factory=list)


@dataclass
class VisualInfo:
    """Informationen zu einer Visualisierung auf einer Berichtsseite."""
    page_name: str
    visual_type: str  # "barChart", "table", "card", etc.
    title: str | None = None  # Technische ID
    display_name: str = ""  # Anzeigename (aus vcObjects.title)
    fields: list[str] = field(default_factory=list)


@dataclass
class DependentReportInfo:
    """Informationen zu einem Bericht, der auf dem Semantic Model basiert."""
    name: str
    report_id: str
    web_url: str = ""


@dataclass
class RefreshScheduleInfo:
    """Informationen zum Aktualisierungszeitplan."""
    frequency: str  # "Daily", "Weekly", etc.
    times: list[str] = field(default_factory=list)
    timezone: str = ""
    days: list[str] | None = None


# ---------------------------------------------------------------------------
# Workspace-Datenklassen (Bulk-Dokumentation eines Fabric-Workspaces)
# ---------------------------------------------------------------------------

@dataclass
class WorkspaceUserInfo:
    """Ein Benutzer oder eine Gruppe mit Zugriff auf den Workspace."""
    display_name: str
    identifier: str  # E-Mail / UPN / Objekt-ID
    principal_type: str  # "User", "Group", "App", "None"
    access_right: str  # "Admin", "Member", "Contributor", "Viewer"


@dataclass
class WorkspaceItemInfo:
    """Ein Element (Artefakt) innerhalb eines Fabric-Workspaces.

    Deckt Berichte, Semantic Models sowie sonstige Artefakte
    (Dashboards, Dataflows, Paginated Reports usw.) ab.
    """
    id: str
    name: str
    item_type: str  # "Report", "SemanticModel", "Dashboard", "Dataflow", ...
    dataset_id: str = ""  # Nur bei Berichten: gebundenes Semantic Model
    web_url: str = ""
    description: str = ""
    endorsement: str = ""  # "Promoted", "Certified" oder ""
    configured_by: str = ""


@dataclass
class WorkspaceMetadata:
    """Gesammelte Metadaten eines Fabric-Workspaces (ohne Detail-Extraktion)."""
    workspace_id: str
    workspace_name: str
    description: str = ""
    capacity_id: str = ""
    workspace_type: str = ""
    is_on_dedicated_capacity: bool = False
    users: list[WorkspaceUserInfo] = field(default_factory=list)
    reports: list[WorkspaceItemInfo] = field(default_factory=list)
    datasets: list[WorkspaceItemInfo] = field(default_factory=list)
    other_items: list[WorkspaceItemInfo] = field(default_factory=list)
    extracted_at: str = ""


# ---------------------------------------------------------------------------
# Template/Parsing Datenklassen
# ---------------------------------------------------------------------------

@dataclass
class Placeholder:
    """Ein im Template gefundener Platzhalter."""
    name: str
    position: int
    line: int
    section: str
    context: str


@dataclass
class ParseResult:
    """Ergebnis des Template-Parsings."""
    placeholders: list[Placeholder] = field(default_factory=list)
    template_content: str = ""
    sections: list[str] = field(default_factory=list)


@dataclass
class PlaceholderMapping:
    """Zuordnung eines Platzhalters zu einem Wert."""
    placeholder: Placeholder
    value: str | None
    source: str  # "auto", "manual", "partial"
    confidence: float = 1.0


@dataclass
class PlaceholderCategory:
    """Kategorisierung eines Platzhalters nach Verfügbarkeit."""
    placeholder_name: str
    category: str  # "automatisch", "manuell", "teilweise"
    available_in: list[str] = field(default_factory=list)


@dataclass
class CategorySummary:
    """Zusammenfassung der Platzhalter-Kategorisierung."""
    auto_count: int = 0
    manual_count: int = 0
    partial_count: int = 0
    details: list[PlaceholderCategory] = field(default_factory=list)


# ---------------------------------------------------------------------------
# Verbindungs- und Metadaten-Datenklassen
# ---------------------------------------------------------------------------

@dataclass
class ConnectionConfig:
    """Konfiguration für eine Verbindung zu einer Power BI Quelle."""
    connection_type: str  # "fabric", "local", "pbip"
    params: dict[str, str] = field(default_factory=dict)


@dataclass
class ReportMetadata:
    """Gesammelte Metadaten eines Power BI Berichts."""
    report_name: str
    tables: list[TableInfo] = field(default_factory=list)
    measures: list[MeasureInfo] = field(default_factory=list)
    columns: list[ColumnInfo] = field(default_factory=list)
    relationships: list[RelationshipInfo] = field(default_factory=list)
    data_sources: list[DataSourceInfo] = field(default_factory=list)
    power_queries: list[PowerQueryInfo] = field(default_factory=list)
    rls_roles: list[RLSRoleInfo] = field(default_factory=list)
    visuals: list[VisualInfo] = field(default_factory=list)
    dependent_reports: list[DependentReportInfo] = field(default_factory=list)
    refresh_schedule: RefreshScheduleInfo | None = None
    report_users: list[WorkspaceUserInfo] = field(default_factory=list)
    raw_metadata: dict = field(default_factory=dict)


# ---------------------------------------------------------------------------
# Versionierungs-Datenklassen
# ---------------------------------------------------------------------------

@dataclass
class Change:
    """Eine erkannte Änderung zwischen zwei Dokumentversionen."""
    field: str
    old_value: str
    new_value: str
    change_type: str  # "fachlich", "technisch"


@dataclass
class ExistingDocInfo:
    """Informationen aus einer bestehenden Dokumentation."""
    version: str
    values: dict[str, str] = field(default_factory=dict)
    changelog: list[dict] = field(default_factory=list)
    last_updated: str = ""


# ---------------------------------------------------------------------------
# Fehlerklassen
# ---------------------------------------------------------------------------

class TemplateParseError(Exception):
    """Vorlage kann nicht gelesen oder geparst werden."""


class PBIConnectionError(Exception):
    """Verbindung zu Power BI Quelle fehlgeschlagen.

    Benannt als PBIConnectionError um Shadowing des builtin
    ConnectionError zu vermeiden.
    """


class AuthenticationError(Exception):
    """Authentifizierung fehlgeschlagen (Fabric Service)."""


class MetadataExtractionError(Exception):
    """Einzelnes Metadatum kann nicht extrahiert werden."""


class PBIPStructureError(Exception):
    """PBIP-Ordner enthält keine gültigen Dateien."""


class PBIPFileReadError(Exception):
    """Einzelne PBIP-Datei nicht lesbar."""


class RenderError(Exception):
    """Fehler beim Erzeugen des Ausgabedokuments."""


class VersionParseError(Exception):
    """Bestehende Dokumentation kann nicht geparst werden."""


class FileWriteError(Exception):
    """Ausgabedokument kann nicht gespeichert werden."""


class BridgeTimeoutError(Exception):
    """Backend-Operation hat das Zeitlimit überschritten."""


class CancelledError(Exception):
    """Operation wurde vom Benutzer abgebrochen."""
