"""Symbol and CallEdge dataclasses with utility functions."""

import hashlib
from dataclasses import dataclass, field
from typing import Optional


@dataclass
class Symbol:
    """A code symbol extracted from source via tree-sitter.

    Symbols represent functions, classes, methods, constants, types,
    and interfaces found in source code. Each has byte offsets for
    O(1) source retrieval without reading the entire file.
    """

    id: str
    file: str
    name: str
    qualified_name: str
    kind: str  # function | class | method | constant | type | interface
    language: str
    signature: str
    docstring: str = ''
    decorators: list[str] = field(default_factory=list)
    parent: Optional[str] = None
    line: int = 0
    end_line: int = 0
    byte_offset: int = 0
    byte_length: int = 0
    content_hash: str = ''


@dataclass
class CallEdge:
    """An edge in the call graph: caller -> callee."""

    callee_name: str
    line: int
    callee_qualified: str = ''


def make_symbol_id(file_path: str, qualified_name: str, kind: str = '') -> str:
    """Generate unique symbol ID.

    Format: {file_path}::{qualified_name}#{kind}
    Example: src/main.py::MyClass.login#method
    """
    if kind:
        return f'{file_path}::{qualified_name}#{kind}'
    return f'{file_path}::{qualified_name}'


def compute_content_hash(source_bytes: bytes) -> str:
    """Compute SHA-256 hash of source bytes for change detection."""
    return hashlib.sha256(source_bytes).hexdigest()


def compute_file_hash(file_path: str) -> str:
    """Compute SHA-256 hash of an entire file."""
    h = hashlib.sha256()
    with open(file_path, 'rb') as f:
        for chunk in iter(lambda: f.read(8192), b''):
            h.update(chunk)
    return h.hexdigest()
