import json
from pathlib import Path


CATALOG_PATH = Path(__file__).parent / "catalog.json"
METRICS_PATH = Path(__file__).parent / "metrics.json"


class SemanticCatalog:
    """
    Central metadata provider for the Schema Layer.

    Responsibilities
    ----------------
    - Entity metadata
    - Physical table lookup
    - Count column lookup
    - Measure lookup
    - Filter lookup
    - Dimension lookup
    - Metric lookup

    This class contains NO business logic.
    """

    def __init__(self):

        with open(CATALOG_PATH, "r", encoding="utf-8") as f:
            self.catalog = json.load(f)

        with open(METRICS_PATH, "r", encoding="utf-8") as f:
            self.metrics = json.load(f)

    # -------------------------------------------------------------
    # Entity
    # -------------------------------------------------------------

    def _normalize(self, value: str) -> str:
        return value.strip().lower()

    def get_entity(self, entity_name: str):

        return self.catalog["entities"].get(
            self._normalize(entity_name)
        )

    def has_entity(self, entity_name: str) -> bool:

        return (
            self._normalize(entity_name)
            in self.catalog["entities"]
        )

    def get_all_entities(self):

        return list(
            self.catalog["entities"].keys()
        )

    # -------------------------------------------------------------
    # Table
    # -------------------------------------------------------------

    def get_table(self, entity_name: str):

        entity = self.get_entity(entity_name)

        if entity is None:
            return None

        return entity.get("table")

    # -------------------------------------------------------------
    # Count Column
    # -------------------------------------------------------------

    def get_count_column(self, entity_name: str):

        entity = self.get_entity(entity_name)

        if entity is None:
            return None

        return entity.get("count_column")

    # -------------------------------------------------------------
    # Base Filter
    # -------------------------------------------------------------

    def get_base_filter(self, entity_name: str):

        entity = self.get_entity(entity_name)

        if entity is None:
            return {}

        return entity.get(
            "base_filter",
            {},
        )

    # -------------------------------------------------------------
    # Outputs
    # -------------------------------------------------------------    
    def get_outputs(self, entity_name: str):
        entity = self.get_entity(entity_name)
        if entity is None:
            return {}

        return entity.get(
            "outputs",
            {},
        )  
    def get_output(
            self,
            entity_name: str,
            output_name: str,
        ):

            return self.get_outputs(
                entity_name,
            ).get(
                self._normalize(output_name)
            )
    # -------------------------------------------------------------
    # Filters
    # -------------------------------------------------------------

    def get_filters(self, entity_name: str):

        entity = self.get_entity(entity_name)

        if entity is None:
            return {}

        return entity.get(
            "filters",
            {},
        )

    def get_filter(
        self,
        entity_name: str,
        filter_name: str,
    ):

        return self.get_filters(
            entity_name,
        ).get(
            self._normalize(filter_name)
        )

    # -------------------------------------------------------------
    # Dimensions
    # -------------------------------------------------------------

    def get_dimensions(self, entity_name: str):

        entity = self.get_entity(entity_name)

        if entity is None:
            return {}

        return entity.get(
            "group_by_columns",
            {},
        )

    def get_dimension(
        self,
        entity_name: str,
        dimension_name: str,
    ):

        return self.get_dimensions(
            entity_name,
        ).get(
            self._normalize(dimension_name)
        )

    # -------------------------------------------------------------
    # Measure Columns
    # -------------------------------------------------------------

    def get_measures(self, entity_name: str):

        entity = self.get_entity(entity_name)

        if entity is None:
            return {}

        return entity.get(
            "measure_columns",
            {},
        )

    def get_measure(
        self,
        entity_name: str,
        measure_name: str,
    ):

        return self.get_measures(
            entity_name,
        ).get(
            self._normalize(measure_name)
        )

    # -------------------------------------------------------------
    # Metrics
    # -------------------------------------------------------------

    def get_metric(
        self,
        metric_name: str,
    ):

        return self.metrics.get(
            self._normalize(metric_name)
        )

    def has_metric(
        self,
        metric_name: str,
    ):

        return (
            self._normalize(metric_name)
            in self.metrics
        )


semantic_catalog = SemanticCatalog()