"""Auto-generated from proto/nexus/core/metadata.proto - DO NOT EDIT.

This module is generated by: python scripts/gen_metadata.py
SSOT: proto/nexus/core/metadata.proto

To modify FileMetadata:
  1. Edit proto/nexus/core/metadata.proto
  2. Run: python scripts/gen_metadata.py
  3. Never edit this file directly!

Contains:
  - FileMetadata: Core file metadata dataclass
  - DT_REG, DT_DIR, DT_MOUNT, DT_PIPE, DT_STREAM, DT_EXTERNAL_STORAGE: Directory entry type constants
"""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from nexus.core._compact_generated import CompactFileMetadata


# DirEntryType (from proto/nexus/core/metadata.proto)
DT_REG = 0
DT_DIR = 1
DT_MOUNT = 2
DT_PIPE = 3
DT_STREAM = 4
DT_EXTERNAL_STORAGE = 5
DT_LINK = 6


@dataclass(slots=True)
class FileMetadata:
    """File metadata information.

    Generated from: proto/nexus/core/metadata.proto
    """

    path: str
    size: int
    content_id: str | None = None
    mime_type: str | None = None
    created_at: datetime | None = None
    modified_at: datetime | None = None
    version: int = 1
    zone_id: str | None = None
    owner_id: str | None = None
    entry_type: int = 0
    target_zone_id: str | None = None
    ttl_seconds: float = 0.0
    last_writer_address: str | None = None
    link_target: str | None = None
    gen: int = 0

    @property
    def is_reg(self) -> bool:
        return self.entry_type == 0

    @property
    def is_dir(self) -> bool:
        return self.entry_type == 1

    @property
    def is_mount(self) -> bool:
        return self.entry_type == 2

    @property
    def is_pipe(self) -> bool:
        return self.entry_type == 3

    @property
    def is_stream(self) -> bool:
        return self.entry_type == 4

    @property
    def is_external_storage(self) -> bool:
        return self.entry_type == 5

    @property
    def is_link(self) -> bool:
        return self.entry_type == 6

    def to_dict(self) -> dict[str, Any]:
        """Serialize to JSON-compatible dict.

        Handles datetime -> ISO 8601 string conversion.
        Generated from proto field definitions (SSOT).
        """
        return {
            "path": self.path,
            "size": self.size,
            "content_id": self.content_id,
            "mime_type": self.mime_type,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "modified_at": self.modified_at.isoformat() if self.modified_at else None,
            "version": self.version,
            "zone_id": self.zone_id,
            "owner_id": self.owner_id,
            "entry_type": self.entry_type,
            "target_zone_id": self.target_zone_id,
            "ttl_seconds": self.ttl_seconds,
            "last_writer_address": self.last_writer_address,
            "link_target": self.link_target,
            "gen": self.gen,
        }

    def validate(self) -> None:
        """Validate file metadata before database operations.

        Raises:
            ValidationError: If validation fails with clear message.
        """
        from nexus.contracts.exceptions import ValidationError

        if not self.path:
            raise ValidationError("path is required")

        if not self.path.startswith("/"):
            raise ValidationError(f"path must start with '/', got {self.path!r}", path=self.path)

        if "\x00" in self.path:
            raise ValidationError("path contains null bytes", path=self.path)

        if self.gen < 0:
            raise ValidationError(f"gen cannot be negative, got {self.gen}", path=self.path)

        # DT_PIPE/DT_STREAM inodes: in-memory buffers, no backend storage required
        if self.entry_type in (3, 4):  # DT_PIPE, DT_STREAM
            return

        if self.size < 0:
            raise ValidationError(f"size cannot be negative, got {self.size}", path=self.path)

        if self.version < 1:
            raise ValidationError(f"version must be >= 1, got {self.version}", path=self.path)

    def to_compact(self) -> CompactFileMetadata:
        """Convert to memory-efficient CompactFileMetadata.

        Uses string interning to deduplicate path/hash strings across instances.
        Reduces memory from ~200-300 bytes to ~64-100 bytes per instance.

        Returns:
            CompactFileMetadata with interned strings and packed fields
        """
        from nexus.core._compact_generated import CompactFileMetadata

        return CompactFileMetadata.from_file_metadata(self)

    @classmethod
    def from_compact(cls, compact: CompactFileMetadata) -> FileMetadata:
        """Create FileMetadata from CompactFileMetadata.

        Resolves interned string IDs back to full strings.

        Args:
            compact: CompactFileMetadata instance

        Returns:
            Full FileMetadata object
        """
        return compact.to_file_metadata()
