#!/usr/bin/env python3
"""
SeedStore for .hxz capsules (WO#22).

Content-addressed storage using SHA256-based layout:
  vault_root/ab/cd/abcdef...hxz

See: ECHO_SEED_MEMORY_SPEC.md, ECHO_HELIX_MEMORY_LAYER_V1.md
"""

import hashlib
import shutil
from pathlib import Path
from typing import Optional, Union


class SeedStore:
    """
    Content-addressed .hxz seed store.

    Uses SHA256 hex digest as anchor ID with hierarchical layout:
      vault_root/{anchor[0:2]}/{anchor[2:4]}/{anchor}.hxz
    """

    def __init__(self, vault_root: Union[Path, str] = Path("crystal_vault")):
        """
        Initialize SeedStore.

        Args:
            vault_root: Root directory for content-addressed storage
        """
        self.vault_root = Path(vault_root)
        self.vault_root.mkdir(parents=True, exist_ok=True)

    def compute_anchor(self, seed_path: Path) -> str:
        """
        Compute SHA256 hex digest for the given file.

        Args:
            seed_path: Path to the .hxz file

        Returns:
            Lowercase hex digest string (64 chars)
        """
        sha256 = hashlib.sha256()

        with open(seed_path, "rb") as f:
            # Read in chunks for large files
            while chunk := f.read(65536):
                sha256.update(chunk)

        return sha256.hexdigest()

    def store(self, seed_path: Path) -> str:
        """
        Store .hxz seed in content-addressed layout.

        Args:
            seed_path: Path to source .hxz file

        Returns:
            anchor_id (SHA256 hex digest)
        """
        seed_path = Path(seed_path)

        if not seed_path.exists():
            raise FileNotFoundError(f"Seed file not found: {seed_path}")

        # Compute anchor
        anchor = self.compute_anchor(seed_path)

        # Derive canonical path
        subdir = self.vault_root / anchor[:2] / anchor[2:4]
        filename = f"{anchor}.hxz"
        dest = subdir / filename

        # If already exists, don't overwrite
        if dest.exists():
            return anchor

        # Create dirs and copy
        subdir.mkdir(parents=True, exist_ok=True)
        shutil.copy2(seed_path, dest)

        return anchor

    def resolve(self, anchor_id: str) -> Optional[Path]:
        """
        Return path to stored .hxz for this anchor_id, or None if missing.

        Args:
            anchor_id: SHA256 hex digest

        Returns:
            Path to stored file, or None if not found
        """
        # Normalize anchor
        anchor = anchor_id.lower()

        # Compute expected path
        subdir = self.vault_root / anchor[:2] / anchor[2:4]
        filename = f"{anchor}.hxz"
        path = subdir / filename

        if path.exists():
            return path

        return None

    def exists(self, anchor_id: str) -> bool:
        """Check if anchor exists in store."""
        return self.resolve(anchor_id) is not None

    def list_anchors(self) -> list[str]:
        """List all anchors in the store."""
        anchors = []
        for hxz_file in self.vault_root.rglob("*.hxz"):
            # Extract anchor from filename
            anchor = hxz_file.stem
            if len(anchor) == 64:  # Valid SHA256 hex
                anchors.append(anchor)
        return anchors
