from typing import Callable

from sandwich.modeling.dataclasses import StgInfo, Dv2SystemInfo, ValidationResult
from sandwich.modeling.metadata import modeling_metadata

from .abc_validator import Validator


class BaseValidator(Validator):
    """Validates required columns (LoadDate, RecordSource)\n
    Transforms `stg_info` input param into `ValidationResult` return value
    """
    def __init__(self, profile: str):
        self._on_validate_staging: list[Callable[[StgInfo, Dv2SystemInfo], None]] = []
        self.profile = profile

    def validate_staging(self, stg_info: StgInfo, sys_info: Dv2SystemInfo, verbose: bool = False) -> ValidationResult:
        """Raises: Exception"""
        if verbose:
            raise Exception("verbose is not implemented yet")

        system_column_names = stg_info.sys_columns.keys()

        # universal check - all dv2 raw objects should be auditable
        for required_col in modeling_metadata.required_columns:
            if required_col not in system_column_names:
                raise Exception(f"{required_col} column is required")

        # extension point
        for on_validate_staging in self._on_validate_staging:
            on_validate_staging(stg_info, sys_info)

        # todo: ValidationResult is not required whatsoever
        return ValidationResult(
            stg_schema=stg_info.stg_schema,
            entity_name=stg_info.stg_name,
            bk_keys=[(nm, tp) for nm, tp in stg_info.bk_keys.items()],
            hk_keys=[(nm, tp) for nm, tp in stg_info.hk_keys.items()],
            degenerate_field = stg_info.degenerate_field,
            business_column_types=stg_info.bus_columns,
            system_column_types=stg_info.sys_columns,
            profile=self.profile
        )
