"""
Cold archive export for long-term evidence preservation.

Produces a self-describing archive containing everything needed to
reconstitute a SooSeF evidence store on a fresh instance or verify
evidence decades later without any SooSeF installation.

Designed for OAIS (ISO 14721) alignment: the archive is self-describing,
includes its own verification code, and documents the cryptographic
algorithms used.
"""

from __future__ import annotations

import hashlib
import json
import zipfile
from datetime import UTC, datetime
from pathlib import Path


def export_cold_archive(
    output_path: Path,
    include_keys: bool = True,
    key_password: bytes | None = None,
) -> dict:
    """Export a full cold archive of the SooSeF evidence store.

    Contents:
    - chain/chain.bin — raw append-only hash chain
    - chain/state.cbor — chain state checkpoint
    - chain/anchors/ — external timestamp anchors
    - attestations/log.bin — verisoo attestation log
    - attestations/index/ — LMDB index (if present)
    - keys/public.pem — signer's public key
    - keys/bundle.enc — encrypted key bundle (if include_keys + password)
    - keys/trusted/ — trusted collaborator keys
    - manifest.json — archive metadata and integrity hashes
    - verify.py — standalone verification script
    - ALGORITHMS.txt — cryptographic algorithm documentation
    - README.txt — human-readable description

    Args:
        output_path: Where to write the ZIP.
        include_keys: Whether to include the encrypted key bundle.
        key_password: Password for encrypting the key bundle.

    Returns:
        Summary dict with archive contents.
    """
    import shutil

    from soosef.paths import (
        ATTESTATIONS_DIR,
        CHAIN_DIR,
        IDENTITY_DIR,
        IDENTITY_PUBLIC_KEY,
    )

    ts = datetime.now(UTC)
    contents = []

    with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:

        # Chain data
        chain_bin = CHAIN_DIR / "chain.bin"
        if chain_bin.exists():
            zf.write(chain_bin, "chain/chain.bin")
            contents.append("chain/chain.bin")

        state_cbor = CHAIN_DIR / "state.cbor"
        if state_cbor.exists():
            zf.write(state_cbor, "chain/state.cbor")
            contents.append("chain/state.cbor")

        anchors_dir = CHAIN_DIR / "anchors"
        if anchors_dir.exists():
            for anchor_file in anchors_dir.glob("*.json"):
                zf.write(anchor_file, f"chain/anchors/{anchor_file.name}")
                contents.append(f"chain/anchors/{anchor_file.name}")

        # Attestation log
        log_bin = ATTESTATIONS_DIR / "log.bin"
        if log_bin.exists():
            zf.write(log_bin, "attestations/log.bin")
            contents.append("attestations/log.bin")

        # LMDB index
        lmdb_dir = ATTESTATIONS_DIR / "index"
        if lmdb_dir.exists():
            for f in lmdb_dir.iterdir():
                if f.name != "lock.mdb":  # Skip lock file
                    zf.write(f, f"attestations/index/{f.name}")
                    contents.append(f"attestations/index/{f.name}")

        # Public key (always included — not secret)
        if IDENTITY_PUBLIC_KEY.exists():
            zf.write(IDENTITY_PUBLIC_KEY, "keys/public.pem")
            contents.append("keys/public.pem")

        # Trusted keys
        trusted_dir = IDENTITY_DIR.parent / "trusted_keys"
        if trusted_dir.exists():
            for key_dir in trusted_dir.iterdir():
                for f in key_dir.iterdir():
                    arcname = f"keys/trusted/{key_dir.name}/{f.name}"
                    zf.write(f, arcname)
                    contents.append(arcname)

        # Encrypted key bundle (optional)
        if include_keys and key_password:
            from soosef.keystore.export import export_bundle
            from soosef.paths import CHANNEL_KEY_FILE

            import tempfile

            with tempfile.NamedTemporaryFile(suffix=".enc", delete=False) as tmp:
                tmp_path = Path(tmp.name)
            try:
                export_bundle(IDENTITY_DIR, CHANNEL_KEY_FILE, tmp_path, key_password)
                zf.write(tmp_path, "keys/bundle.enc")
                contents.append("keys/bundle.enc")
            except Exception:
                pass
            finally:
                tmp_path.unlink(missing_ok=True)

        # Algorithm documentation
        algorithms = """SOOSEF CRYPTOGRAPHIC ALGORITHMS
================================

This archive uses the following algorithms:

SIGNING
- Ed25519 (RFC 8032): 32-byte public keys, 64-byte signatures
- Used for: attestation records, chain records, verification receipts

HASHING
- SHA-256: content hashing, chain linkage, fingerprints
- pHash (DCT perceptual hash): image similarity matching
- dHash (difference hash): image similarity matching

ENCRYPTION (key bundle only)
- AES-256-GCM: authenticated encryption
- Argon2id (RFC 9106): key derivation from password
  Parameters: time_cost=4, memory_cost=256MB, parallelism=4

CHAIN FORMAT
- Append-only binary log: [uint32 BE length] [CBOR record]*
- CBOR (RFC 8949): deterministic serialization
- Each record signed by Ed25519, linked by prev_hash (SHA-256)

ATTESTATION LOG
- Verisoo binary log: [magic "VERISOO\\x00"] [uint32 version] [records]
- LMDB index: SHA-256, pHash, attestor fingerprint lookups

To verify this archive without SooSeF:
1. pip install cryptography cbor2
2. python verify.py
"""
        zf.writestr("ALGORITHMS.txt", algorithms)
        contents.append("ALGORITHMS.txt")

        # Manifest
        manifest = {
            "archive_version": "1",
            "created_at": ts.isoformat(),
            "soosef_version": "0.2.0",
            "contents": contents,
            "file_count": len(contents),
            "content_hashes": {},
        }

        # Compute hashes of key files for integrity verification
        for name in ["chain/chain.bin", "attestations/log.bin"]:
            try:
                data = zf.read(name)
                manifest["content_hashes"][name] = hashlib.sha256(data).hexdigest()
            except KeyError:
                pass

        zf.writestr("manifest.json", json.dumps(manifest, indent=2))
        contents.append("manifest.json")

        # README
        readme = f"""SOOSEF COLD ARCHIVE
===================

Created: {ts.isoformat()}
Files: {len(contents)}

This archive contains a complete snapshot of a SooSeF evidence store.
It is self-describing and includes everything needed to verify the
evidence it contains, even if SooSeF no longer exists.

See ALGORITHMS.txt for cryptographic algorithm documentation.
Run verify.py to check archive integrity.

To restore on a fresh SooSeF instance:
  soosef archive import <this-file.zip>
"""
        zf.writestr("README.txt", readme)

    return {
        "path": str(output_path),
        "file_count": len(contents),
        "created_at": ts.isoformat(),
    }
