"""ID allocation and content-hash deduplication for package building.

Inspired by svg2ooxml's PackagingContext pattern:
- Deterministic ID allocation (no collisions across fonts/relationships)
- MD5-based content dedup (same font bytes -> same entry)
"""

from __future__ import annotations

import hashlib
from pathlib import PurePosixPath


class PackagingContext:
    """Allocate unique relationship IDs and deduplicate content by hash."""

    def __init__(self, initial_rel_id: int = 1) -> None:
        self._next_rel_id = initial_rel_id
        self._content_by_hash: dict[str, str] = {}
        self._used_archive_paths: set[str] = set()

    def allocate_rel_id(self) -> str:
        """Return the next available relationship ID (e.g. 'rId3')."""
        rel_id = f"rId{self._next_rel_id}"
        self._next_rel_id += 1
        return rel_id

    @property
    def next_rel_id_number(self) -> int:
        """Current counter value (next ID to be allocated)."""
        return self._next_rel_id

    def deduplicate(self, data: bytes, proposed_path: str) -> tuple[str, bool]:
        """Check if identical content already exists in the package.

        Returns:
            (archive_path, is_new): The path to use and whether this is new.
        """
        digest = hashlib.md5(data, usedforsecurity=False).hexdigest()
        existing = self._content_by_hash.get(digest)
        if existing is not None:
            return existing, False

        path = proposed_path
        counter = 1
        while path in self._used_archive_paths:
            p = PurePosixPath(proposed_path)
            path = str(p.parent / f"{p.stem}_{counter}{p.suffix}")
            counter += 1

        self._content_by_hash[digest] = path
        self._used_archive_paths.add(path)
        return path, True

    def register_path(self, archive_path: str) -> None:
        """Register a path as used without content dedup."""
        self._used_archive_paths.add(archive_path)
