from __future__ import annotations

from typing import Any, Callable, Iterable, Iterator, List, Mapping, Optional, Sequence, Tuple, Union

# Public module API (manually authored for v1)

# ---- Convenience functions ----
class FormulaDialect:
    Excel: FormulaDialect
    OpenFormula: FormulaDialect

class WorkbookMode:
    Ephemeral: WorkbookMode
    Interactive: WorkbookMode

class WorkbookConfig:
    def __init__(
        self,
        *,
        mode: WorkbookMode = ...,
        eval_config: Optional[EvaluationConfig] = ...,
        enable_changelog: Optional[bool] = ...,
    ) -> None: ...

def tokenize(formula: str, dialect: Optional[FormulaDialect] = None) -> Tokenizer: ...
def parse(formula: str, dialect: Optional[FormulaDialect] = None) -> ASTNode: ...
def load_workbook(path: str, strategy: Optional[str] = None) -> Workbook: ...

# ---- Tokenizer / Token ----
class Token:
    @property
    def value(self) -> str: ...
    @property
    def token_type(self) -> str: ...
    @property
    def subtype(self) -> str: ...
    @property
    def start(self) -> int: ...
    @property
    def end(self) -> int: ...
    def to_dict(self) -> dict: ...
    def is_operator(self) -> bool: ...
    def get_precedence(self) -> Optional[Tuple[int, str]]: ...

class Tokenizer(Iterable[Token]):
    def __init__(self, formula: str, dialect: Optional[FormulaDialect] = None) -> None: ...
    def tokens(self) -> List[Token]: ...
    def render(self) -> str: ...
    @property
    def dialect(self) -> FormulaDialect: ...
    def __len__(self) -> int: ...
    def __getitem__(self, index: int) -> Token: ...
    def __iter__(self) -> Iterator[Token]: ...

# ---- AST ----
class ASTNode:
    def to_json(self) -> dict: ...
    def to_string(self) -> str: ...
    def get_type(self) -> str: ...

# ---- Literal values ----
class LiteralValue:
    # Constructors
    @staticmethod
    def int(value: int) -> LiteralValue: ...
    @staticmethod
    def number(value: float) -> LiteralValue: ...
    @staticmethod
    def boolean(value: bool) -> LiteralValue: ...
    @staticmethod
    def text(value: str) -> LiteralValue: ...
    @staticmethod
    def empty() -> LiteralValue: ...
    @staticmethod
    def date(year: int, month: int, day: int) -> LiteralValue: ...
    @staticmethod
    def time(hour: int, minute: int, second: int) -> LiteralValue: ...
    @staticmethod
    def datetime(year: int, month: int, day: int, hour: int, minute: int, second: int) -> LiteralValue: ...
    @staticmethod
    def duration(seconds: int) -> LiteralValue: ...
    @staticmethod
    def array(values: List[List[LiteralValue]]) -> LiteralValue: ...
    @staticmethod
    def error(kind: str, message: Optional[str] = None) -> LiteralValue: ...

    # Extractors
    def as_int(self) -> int: ...
    def as_number(self) -> float: ...
    def to_python(self) -> Any: ...

    # Introspection
    @property
    def type_name(self) -> str: ...
    @property
    def is_int(self) -> bool: ...
    @property
    def is_number(self) -> bool: ...
    @property
    def is_boolean(self) -> bool: ...
    @property
    def is_text(self) -> bool: ...
    @property
    def is_empty(self) -> bool: ...
    @property
    def is_date(self) -> bool: ...
    @property
    def is_time(self) -> bool: ...
    @property
    def is_datetime(self) -> bool: ...
    @property
    def is_duration(self) -> bool: ...
    @property
    def is_array(self) -> bool: ...
    @property
    def is_error(self) -> bool: ...
    @property
    def is_pending(self) -> bool: ...
    @property
    def error_kind(self) -> Optional[str]: ...
    @property
    def error_message(self) -> Optional[str]: ...
    @property
    def error_location(self) -> Optional[Tuple[int, int]]: ...
    @property
    def error_origin(self) -> Optional[Tuple[Optional[str], int, int]]: ...

# ---- Workbook / Sheet ----
class Cell:
    @property
    def value(self) -> Any: ...
    @property
    def formula(self) -> Optional[str]: ...

class RangeAddress:
    def __init__(self, sheet: str, start_row: int, start_col: int, end_row: int, end_col: int) -> None: ...

class Sheet:
    name: str
    def set_value(self, row: int, col: int, value: Any) -> None: ...
    def set_formula(self, row: int, col: int, formula: str) -> None: ...
    def get_cell(self, row: int, col: int) -> Cell: ...
    def set_values_batch(self, start_row: int, start_col: int, rows: int, cols: int, data: List[List[Any]]) -> None: ...
    def set_formulas_batch(self, start_row: int, start_col: int, rows: int, cols: int, formulas: List[List[str]]) -> None: ...
    def get_values(self, range: RangeAddress) -> List[List[Any]]: ...
    def get_formulas(self, range: RangeAddress) -> List[List[str]]: ...

class Workbook:
    def __init__(
        self,
        *,
        mode: Optional[WorkbookMode] = ...,
        config: Optional[WorkbookConfig] = ...,
    ) -> None: ...
    @classmethod
    def from_path(
        cls,
        path: str,
        backend: Optional[str] = None,
        *,
        mode: Optional[WorkbookMode] = ...,
        config: Optional[WorkbookConfig] = ...,
    ) -> Workbook: ...
    @classmethod
    def load_path(
        cls,
        path: str,
        strategy: Optional[str] = None,
        backend: Optional[str] = None,
        *,
        mode: Optional[WorkbookMode] = ...,
        config: Optional[WorkbookConfig] = ...,
    ) -> Workbook: ...
    def add_sheet(self, name: str) -> None: ...
    @property
    def sheet_names(self) -> List[str]: ...
    def sheet(self, name: str) -> Sheet: ...
    def __getitem__(self, name: str) -> Sheet: ...
    # Single cell ops
    def set_value(self, sheet: str, row: int, col: int, value: Any) -> None: ...
    def set_formula(self, sheet: str, row: int, col: int, formula: str) -> None: ...
    def get_value(self, sheet: str, row: int, col: int) -> Optional[Any]: ...
    def get_formula(self, sheet: str, row: int, col: int) -> Optional[str]: ...
    def evaluate_cell(self, sheet: str, row: int, col: int) -> Any: ...
    # Batch ops (auto‑grouped when changelog enabled)
    def set_values_batch(self, sheet: str, start_row: int, start_col: int, data: List[List[Any]]) -> None: ...
    def set_formulas_batch(self, sheet: str, start_row: int, start_col: int, formulas: List[List[str]]) -> None: ...
    def get_eval_plan(self, targets: List[Tuple[str, int, int]]) -> EvaluationPlan: ...
    # Changelog controls (optional)
    def set_changelog_enabled(self, enabled: bool) -> None: ...
    def begin_action(self, description: str) -> None: ...
    def end_action(self) -> None: ...
    def undo(self) -> None: ...
    def redo(self) -> None: ...

# ---- SheetPort ----
class SheetPortError(Exception): ...
class SheetPortManifestError(SheetPortError): ...
class SheetPortConstraintError(SheetPortError): ...
class SheetPortWorkbookError(SheetPortError): ...

class SheetPortSession:
    @classmethod
    def from_manifest_path(
        cls,
        manifest_path: str,
        workbook_path: str,
        backend: Optional[str] = None,
    ) -> SheetPortSession: ...
    @classmethod
    def from_manifest_yaml(cls, manifest_yaml: str, workbook: Workbook) -> SheetPortSession: ...
    @property
    def manifest(self) -> Mapping[str, Any]: ...
    def describe_ports(self) -> List[Mapping[str, Any]]: ...
    def read_inputs(self) -> Mapping[str, Any]: ...
    def read_outputs(self) -> Mapping[str, Any]: ...
    def write_inputs(self, update: Mapping[str, Any]) -> None: ...
    def evaluate_once(
        self,
        *,
        freeze_volatile: bool = ...,
        rng_seed: Optional[int] = ...,
    ) -> Mapping[str, Any]: ...

class EvaluationConfig:
    def __init__(self) -> None: ...
    # Common toggles
    def set_enable_parallel(self, value: bool) -> None: ...
    def get_enable_parallel(self) -> bool: ...
    def set_max_threads(self, value: Optional[int]) -> None: ...
    def get_max_threads(self) -> Optional[int]: ...
    def set_range_expansion_limit(self, value: int) -> None: ...
    def get_range_expansion_limit(self) -> int: ...
    def set_workbook_seed(self, value: int) -> None: ...
    def get_workbook_seed(self) -> int: ...
    # Warmup subset
    def set_warmup_enabled(self, value: bool) -> None: ...
    def get_warmup_enabled(self) -> bool: ...
    def set_warmup_time_budget_ms(self, value: int) -> None: ...
    def get_warmup_time_budget_ms(self) -> int: ...
    def set_warmup_parallelism_cap(self, value: int) -> None: ...
    def get_warmup_parallelism_cap(self) -> int: ...
    def set_warmup_topk_refs(self, value: int) -> None: ...
    def get_warmup_topk_refs(self) -> int: ...
    def set_min_flat_cells(self, value: int) -> None: ...
    def get_min_flat_cells(self) -> int: ...
    def set_flat_cache_mb_cap(self, value: int) -> None: ...
    def get_flat_cache_mb_cap(self) -> int: ...
    def get_date_system(self) -> str: ...
    def set_date_system(self, value: str) -> None: ...

class LayerInfo:
    @property
    def vertex_count(self) -> int: ...
    @property
    def parallel_eligible(self) -> bool: ...
    @property
    def sample_cells(self) -> List[str]: ...

class EvaluationPlan:
    @property
    def total_vertices_to_evaluate(self) -> int: ...
    @property
    def layers(self) -> List[LayerInfo]: ...
    @property
    def cycles_detected(self) -> int: ...
    @property
    def dirty_count(self) -> int: ...
    @property
    def volatile_count(self) -> int: ...
    @property
    def parallel_enabled(self) -> bool: ...
    @property
    def estimated_parallel_layers(self) -> int: ...
    @property
    def target_cells(self) -> List[str]: ...


# ---- References (types and union) ----
class CellRef: ...
class RangeRef: ...
class TableRef: ...
class NamedRangeRef: ...
class UnknownRef: ...

ReferenceLike = Union[CellRef, RangeRef, TableRef, NamedRangeRef, UnknownRef]
# ruff: noqa: E501, F401

import builtins
import typing
from enum import Enum

class ASTNode:
    def pretty(self) -> builtins.str:
        r"""
        Get the pretty-printed representation of this AST
        """
    def to_formula(self) -> builtins.str:
        r"""
        Round-trips the node back to canonical Excel formula (with leading '=').
        """
    def fingerprint(self) -> builtins.int:
        r"""
        Get a stable fingerprint hash of this AST structure
        """
    def children(self) -> builtins.list[ASTNode]:
        r"""
        Get immediate children of this AST node
        """
    def walk_refs(self) -> PyRefWalker:
        r"""
        Walk through all references in this AST
        """
    def to_dict(self) -> typing.Any:
        r"""
        Convert AST to a dictionary representation
        """
    def node_type(self) -> builtins.str:
        r"""
        Get the node type as a string
        """
    def get_literal_value(self) -> typing.Optional[typing.Any]:
        r"""
        Get the value for literal nodes
        """
    def get_reference_string(self) -> typing.Optional[builtins.str]:
        r"""
        Get the reference string for reference nodes
        """
    def get_reference(self) -> typing.Optional[typing.Any]:
        r"""
        Get the reference as a rich object for reference nodes
        """
    def get_operator(self) -> typing.Optional[builtins.str]:
        r"""
        Get the operator for unary/binary operation nodes
        """
    def get_function_name(self) -> typing.Optional[builtins.str]:
        r"""
        Get the function name for function nodes
        """
    def get_source_token(self) -> typing.Optional[PyToken]:
        r"""
        Get the source token if available
        """
    def __repr__(self) -> builtins.str: ...
    def __str__(self) -> builtins.str: ...

class CellRef:
    sheet: typing.Optional[builtins.str]
    row: builtins.int
    col: builtins.int
    abs_row: builtins.bool
    abs_col: builtins.bool

class PyRefWalker:
    ...

class PyToken:
    value: builtins.str
    token_type: PyTokenType
    subtype: PyTokenSubType
    start: builtins.int
    end: builtins.int
    def __repr__(self) -> builtins.str: ...
    def __str__(self) -> builtins.str: ...
    def to_dict(self) -> typing.Any: ...
    def is_operator(self) -> builtins.bool:
        r"""
        Check if this token is an operator
        """
    def get_precedence(self) -> typing.Optional[tuple[builtins.int, builtins.str]]:
        r"""
        Get the precedence of this token (if it's an operator)
        """

class PyTokenizer:
    def __new__(cls, formula:builtins.str) -> PyTokenizer: ...
    def tokens(self) -> builtins.list[PyToken]:
        r"""
        Get all tokens as a list
        """
    def render(self) -> builtins.str:
        r"""
        Reconstruct the original formula from tokens
        """
    def __iter__(self) -> PyTokenizerIter:
        r"""
        Make the tokenizer iterable
        """
    def __len__(self) -> builtins.int: ...
    def __getitem__(self, index:builtins.int) -> PyToken: ...
    def __repr__(self) -> builtins.str: ...

class PyTokenizerIter:
    ...

class RangeRef:
    sheet: typing.Optional[builtins.str]
    start: typing.Optional[CellRef]
    end: typing.Optional[CellRef]
    def __new__(cls, sheet:typing.Optional[builtins.str], start:typing.Optional[CellRef], end:typing.Optional[CellRef]) -> RangeRef: ...
    def __repr__(self) -> builtins.str: ...
    def __str__(self) -> builtins.str: ...

class TableRef:
    name: builtins.str
    spec: typing.Optional[builtins.str]
    def __new__(cls, name:builtins.str, spec:typing.Optional[builtins.str]) -> TableRef: ...
    def __repr__(self) -> builtins.str: ...
    def __str__(self) -> builtins.str: ...

class UnknownRef:
    raw: builtins.str
    def __new__(cls, raw:builtins.str) -> UnknownRef: ...
    def __repr__(self) -> builtins.str: ...
    def __str__(self) -> builtins.str: ...

class PyTokenSubType(Enum):
    r"""
    Python-exposed token subtype enum
    """
    None = ...
    Text = ...
    Number = ...
    Logical = ...
    Error = ...
    Range = ...
    Open = ...
    Close = ...
    Arg = ...
    Row = ...

class PyTokenType(Enum):
    r"""
    Python-exposed token type enum
    """
    Literal = ...
    Operand = ...
    Func = ...
    Array = ...
    Paren = ...
    Sep = ...
    OpPrefix = ...
    OpInfix = ...
    OpPostfix = ...
    Whitespace = ...

def parse(formula:builtins.str) -> ASTNode:    r"""
    Convenience function to parse a formula string
    """

def tokenize(formula:builtins.str) -> PyTokenizer:    r"""
    Convenience function to tokenize a formula string
    """
