from typing import Dict, Union, List
from pydantic import BaseModel, Field

from artefacts.mixins import ContextReader, Artifact
from artefacts.nodes import BaseNodeReference, BaseNode
from artefacts.shared import Metadata


class CatalogNode(BaseNode, BaseModel):
    class Config:
        extra = "ignore"

    unique_id: str
    metadata: dict
    columns: dict
    stats: dict


class CatalogNodeReference(BaseNodeReference):
    pass


class Catalog(Artifact, ContextReader, BaseModel):
    """
    Catalogs artifacts generated by `dbt docs generate`, and contain information about
    the actual state of all the tables tracked by dbt models.

    Examples:

        >>> from artefacts import Project
        >>> project = Project(target='./target')
        >>> print(project.catalog)
        <Catalog v1>

    Attributes:

        metadata (Metadata):
            The [`Metadata`][artefacts.shared.Metadata] associated with the artifact

        source_nodes (dict):
            The source_nodes defined in the dbt project

        errors (Union[None, List[str]]):
            The errors encounted when building the catalog, if any

        nodes (dict):
            The nodes (ie models, tests, seeds, etc) in the catalog

    """

    class Config:
        extra = "ignore"

    metadata: Metadata
    nodes: Dict[CatalogNodeReference, CatalogNode]
    errors: Union[None, List[str]]
    source_nodes: Dict[CatalogNodeReference, CatalogNode] = Field(..., alias="sources")
