"""Declarative package manifest for any document format.

A PackageManifest describes the complete contents of a ZIP package:
- Static entries (XML templates from SSOT, always included)
- Customizable entries (need emitter hook processing)
- Font entries (dynamically added during build)
- ODF mimetype marker (must be first, stored uncompressed)
"""

from __future__ import annotations

from dataclasses import dataclass, field

from tokenmoulds.packaging.types import CompressionMode


@dataclass
class ManifestEntry:
    """A single entry in the package manifest."""

    archive_path: str
    template_name: str
    customizable: bool = False
    compression: CompressionMode = CompressionMode.DEFLATED
    order: int = 100


@dataclass
class PackageManifest:
    """Declarative description of a ZIP package.

    Emitters construct a manifest, then hand it to PackageWriter.
    The writer handles ZIP assembly; the emitter controls content
    through the customize hook.
    """

    entries: list[ManifestEntry] = field(default_factory=list)
    odf_mimetype: str | None = None

    def add_entry(
        self,
        archive_path: str,
        template_name: str,
        *,
        customizable: bool = False,
        compression: CompressionMode = CompressionMode.DEFLATED,
        order: int = 100,
    ) -> None:
        """Add an entry to the manifest."""
        self.entries.append(
            ManifestEntry(
                archive_path=archive_path,
                template_name=template_name,
                customizable=customizable,
                compression=compression,
                order=order,
            )
        )

    @classmethod
    def from_structure_dict(
        cls,
        structure: dict[str, str],
        customizable_paths: set[str],
    ) -> PackageManifest:
        """Create manifest from existing PACKAGE_STRUCTURE dict.

        Migration bridge: existing emitters convert their dicts
        to manifests without changing customization logic.
        """
        manifest = cls()
        for archive_path, template_name in structure.items():
            manifest.add_entry(
                archive_path,
                template_name,
                customizable=archive_path in customizable_paths,
            )
        return manifest

    def sorted_entries(self) -> list[ManifestEntry]:
        """Return entries sorted by order (lowest first)."""
        return sorted(self.entries, key=lambda e: e.order)
