from typing import Any

from sqlalchemy import Table, Engine, Connection, MetaData

from sandwich.modeling.dataclasses import StgInfo
from sandwich.modeling.metadata import modeling_metadata


def get_stg_info(entity_name: str, schema: str, conn: Engine | Connection) -> StgInfo:
    stg = Table(entity_name, MetaData(), schema=schema, autoload_with=conn)

    hk_keys: dict[str, Any] = {}
    bk_keys: dict[str, Any] = {}
    sys_columns: dict[str, Any] = {}
    bus_columns: dict[str, Any] = {}
    degenerate_field: dict[str, Any] = {}

    for col in stg.columns.values():
        if col.name.startswith("hk_"): # hash key
            hk_keys[col.name] = col.type
        elif col.name.startswith("bk_"): # business key
            bk_keys[col.name] = col.type
        elif col.name.startswith("dg_"): # degenerate field (transactional links only)
            degenerate_field[col.name] = col.type
        elif col.name.startswith("sg_"): # surrogate key
            raise Exception(f"sg column '{col.name}' is not implemented yet")
        elif col.name in modeling_metadata.names:
            # type_name = metadata.column_types[col.name]
            # if not str(col.type).startswith(type_name):
            #     raise Exception(f"{col.name} column must be `{type_name}` type, but it is `{str(col.type)}`")
            sys_columns[col.name] = col.type
        else:
            bus_columns[col.name] = col.type

    return StgInfo(
        stg_name=stg.name,
        stg_schema=stg.schema,
        hk_keys=hk_keys,
        bk_keys=bk_keys,
        sys_columns=sys_columns,
        bus_columns=bus_columns,
        degenerate_field=degenerate_field,
    )

def infer_profile(stg_info: StgInfo):
    hk_count = len(stg_info.hk_keys)
    hk_key = list(stg_info.hk_keys.items())[0]
    if hk_count == 0:
        raise Exception("hk column is required for any profile validation")
    elif hk_count > 1:
        return "link-sat0"
    else:
        if hk_key[0] != f"hk_{stg_info.stg_name}":
            return "multi-sat2"
        elif modeling_metadata.hashdiff in stg_info.sys_columns.keys():
            return "hub-sat2-dim2"
        else:
            return "hub"