import base64
import json
import re

_ATHENA_DIALECT = "ATHENA"
_PRESTO_VIEW_PATTERN = re.compile(
    r"/\* Presto View: (?P<payload>.+) \*/",
    re.DOTALL,
)


def _decode_view_definition(definition: str | None) -> str | None:
    """
    Decode legacy Presto-wrapped Glue view definitions when possible.

    Some views are stored as `/* Presto View: <base64> */`. The payload is a
    JSON object whose `originalSql` field contains the readable SQL we want to
    expose for lineage and debugging.
    """
    if not definition:
        return definition

    match = _PRESTO_VIEW_PATTERN.fullmatch(definition)
    if not match:
        return definition

    try:
        decoded = base64.b64decode(match.group("payload")).decode("utf-8")
        payload = json.loads(decoded)
    except (TypeError, UnicodeDecodeError, ValueError):
        return definition

    return payload.get("originalSql") or definition


def _extract_view_definition(raw_table: dict) -> str | None:
    """
    Return the best available SQL definition for a Glue view.

    We prefer the dedicated Athena representation when Glue exposes one. When
    it is not available, we fall back to the legacy view text fields kept for
    compatibility.
    """
    view_definition = raw_table.get("ViewDefinition") or {}
    representations = view_definition.get("Representations") or []
    for representation in representations:
        if representation.get("Dialect") != _ATHENA_DIALECT:
            continue

        definition = representation.get(
            "ViewOriginalText"
        ) or representation.get("ViewExpandedText")
        return _decode_view_definition(definition)

    definition = raw_table.get("ViewOriginalText") or raw_table.get(
        "ViewExpandedText"
    )
    return _decode_view_definition(definition)


def _build_create_view_statement(
    schema_name: str,
    view_name: str,
    definition: str,
) -> str:
    """
    Wrap a Glue view body into a standard CREATE VIEW statement.

    Glue often exposes only the view body SQL, especially after decoding the
    legacy Presto wrapper. Reconstructing a conventional DDL keeps downstream
    parsing aligned with other technologies that already ingest `CREATE VIEW`
    statements directly.
    """
    stripped = definition.lstrip()
    if stripped.upper().startswith("CREATE VIEW"):
        return definition

    return f"CREATE VIEW {schema_name}.{view_name} AS\n{definition}"


def build_view_ddl_row(schema_name: str, raw_table: dict) -> dict | None:
    """
    Convert one Glue raw view table into the serialized DDL payload.

    Non-view tables and views without a usable SQL definition are ignored so
    callers can iterate over Glue tables and simply skip `None` rows.
    """
    if raw_table.get("TableType") != "VIRTUAL_VIEW":
        return None

    definition = _extract_view_definition(raw_table)
    if not definition:
        return None

    view_name = raw_table["Name"]
    return {
        "database_name": None,
        "schema_name": schema_name,
        "view_name": view_name,
        "view_definition": _build_create_view_statement(
            schema_name,
            view_name,
            definition,
        ),
    }
