from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Dict, List, Optional


class SourceType(str, Enum):
    """High-level origin of a document."""

    WEB = "web"
    FILE = "file"
    TEXT = "text"
    API = "api"


class NodeType(str, Enum):
    """Types of nodes that can appear in a document tree or graph."""

    DOCUMENT = "document"
    SECTION = "section"
    PARAGRAPH = "paragraph"
    TABLE = "table"
    FIGURE = "figure"
    SUMMARY = "summary"
    ENTITY = "entity"
    CONCEPT = "concept"


@dataclass
class RawDocument:
    """Raw content plus source-level metadata before parsing.

    This is typically produced by an ingestion step (crawler, file loader, API).
    """

    id: str
    source_type: SourceType
    content: str
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class DocumentNode:
    """Generic hierarchical node used for the DocumentTree."""

    id: str
    node_type: NodeType
    text: Optional[str] = None
    children: List["DocumentNode"] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class DocumentTree:
    """Rooted tree representation of a parsed document."""

    root: DocumentNode
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class GraphNode:
    """Node in the higher-level DocumentGraph."""

    id: str
    node_type: NodeType
    label: Optional[str] = None
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class GraphEdge:
    """Typed edge between nodes in the DocumentGraph."""

    source: str
    target: str
    edge_type: str
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class DocumentGraph:
    """In-memory representation of a document graph."""

    nodes: List[GraphNode]
    edges: List[GraphEdge]
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class DatasetRecipe:
    """Declarative description of how to build a dataset from a DocumentGraph.

    For v0.1 this will likely be loaded from a simple YAML or JSON file and
    interpreted by the recipes subsystem.
    """

    name: str
    description: str
    input_query: str
    prompt_template: str
    output_schema: Dict[str, Any]
    params: Dict[str, Any] = field(default_factory=dict)


@dataclass
class DatasetArtifact:
    """Materialized dataset created from running a recipe."""

    id: str
    recipe_name: str
    storage_path: str
    stats: Dict[str, Any] = field(default_factory=dict)
    metadata: Dict[str, Any] = field(default_factory=dict)

