from sandwich.modeling.dataclasses import StgInfo, Dv2SystemInfo

from .base_validator import BaseValidator


class LinkSat0Validator(BaseValidator):
    def __init__(self, profile: str):
        super().__init__(profile)
        self._on_validate_staging.append(self._validate_staging)

    @staticmethod
    def _validate_staging(stg_info: StgInfo, sys_info: Dv2SystemInfo) -> None:
        # -----------------
        # hk
        # -----------------
        hk_count = len(stg_info.hk_keys)
        stg_full_name = f"stg.{stg_info.stg_name}"

        # so only exactly 2 or 3 columns allowed right now
        if hk_count < 2: # own and at least one foreign
            raise Exception(f"At least 2 hk columns expected in `{stg_full_name}` for the `link-sat0` profile")
        if hk_count > 3:
            raise Exception(f"{hk_count} hk columns in `{stg_full_name}` for the `link-sat0` profile?! Are you sure?")
        if len(stg_info.degenerate_field) == 0:
            raise Exception(f"At least one degenerate field is required for `{stg_full_name}` for the `link-sat0` profile")

        # hk_key = (key_name, key_type)
        hk_keys_copy = list(stg_info.hk_keys.keys()).copy()
        is_own_hk_found = False
        expected_own_hk_column_name = f"hk_{stg_info.stg_name}"

        for hk_name in stg_info.hk_keys.keys():
            if hk_name == expected_own_hk_column_name:
                hk_keys_copy.remove(hk_name)
                is_own_hk_found = True
            else:
                # check that `name` from `hk_[name]` is existing entity
                for en in sys_info.entities_list:
                    # for foreign keys
                    if hk_name == f"hk_{en.entity_name}":
                        hk_keys_copy.remove(hk_name)
                    # for a case when we reference the entity multiple times
                    # assuming foreign HKs are based on business columns from our link table
                    else:
                        for own_col in stg_info.bus_columns.keys():
                            if hk_name == f"hk_{en.entity_name}_{own_col}":
                                hk_keys_copy.remove(hk_name)

        if not is_own_hk_found:
            raise Exception(f"Column `{expected_own_hk_column_name}` has not been found in `{stg_full_name}`")

        if len(hk_keys_copy) > 0:
            raise Exception(f"There are no entities related to `{", ".join(hk_keys_copy)}` columns in the `{stg_full_name}`")

        # -----------------
        # BKs
        # -----------------
        # it should be a warning, not an error
        if len(stg_info.bk_keys) > 0:
            raise Exception("You dont need bk columns for the `link2fact` profile")


