from typing import Dict, List
from pydantic import BaseModel

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


# https://schemas.getdbt.com/dbt/manifest/v3/index.html#nodes
class ManifestNode(BaseNode, BaseModel):
    class Config:
        extra = "allow"

    resource_type: str


class ManifestNodeReference(BaseNodeReference):
    pass


class Manifest(Artifact, ContextReader, BaseModel):
    """
    Manifests are artifacts generated by any dbt command that compiles the dbt project,
    including `dbt compile`, `dbt build`, `dbt docs generate`, etc. The manifest
    contains information about all nodes in the project, including models, tests,
    seeds, etc.

    Examples:

        >>> from artefacts import Project
        >>> project = Project(target='./target')
        >>> print(project.manifest)
        <Manifest v3>
    """

    class Config:
        arbitrary_types_allowed = True

    metadata: Metadata
    nodes: Dict[ManifestNodeReference, ManifestNode]
    child_map: Dict[ManifestNodeReference, List[ManifestNodeReference]]
    parent_map: Dict[ManifestNodeReference, List[ManifestNodeReference]]
