"""Forensic annotation -- update/delete attestation metadata via SDK.

Uses ``CertiSigmaClient.update_metadata()`` and ``delete_metadata()``
to attach case-level notes, tags, or encrypted payloads to existing
attestations.  This turns Census into a lightweight forensic case
management layer on top of CertiSigma.

When ``--encrypt`` is used, metadata is encrypted client-side via
``certisigma.crypto`` (AES-256-GCM) before being sent.  The server
stores only ciphertext and the ``client_encrypted`` flag is set.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Optional


@dataclass
class AnnotationResult:
    attestation_id: str
    success: bool
    source: Optional[str] = None
    extra_data: Optional[dict[str, Any]] = None
    client_encrypted: bool = False
    deleted: bool = False
    error: Optional[str] = None


def _build_extra_data(
    note: str | None = None,
    tag: str | None = None,
    case_id: str | None = None,
    custom: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """Build the extra_data payload from individual fields."""
    data: dict[str, Any] = {}
    if note:
        data["note"] = note
    if tag:
        data["tag"] = tag
    if case_id:
        data["case_id"] = case_id
    if custom:
        data.update(custom)
    return data


def annotate(
    attestation_id: str,
    api_key: str | None = None,
    base_url: str | None = None,
    source: str | None = None,
    note: str | None = None,
    tag: str | None = None,
    case_id: str | None = None,
    custom: dict[str, Any] | None = None,
    encrypt: bool = False,
    encryption_key: str | None = None,
) -> AnnotationResult:
    """Update metadata on an attestation.

    If *encrypt* is True, the extra_data payload is encrypted client-side
    with AES-256-GCM using *encryption_key* (or the key from config).
    """
    from certisigma import CertiSigmaClient, CertiSigmaError

    extra = _build_extra_data(note=note, tag=tag, case_id=case_id, custom=custom)

    client_encrypted = False
    if encrypt:
        try:
            key = _resolve_encryption_key(encryption_key)
            from certisigma.crypto import encrypt_metadata
            extra = encrypt_metadata(extra, key)
            client_encrypted = True
        except (ValueError, TypeError, KeyError) as exc:
            return AnnotationResult(
                attestation_id=attestation_id,
                success=False,
                error=f"Encryption failed: {exc}",
            )

    kwargs: dict[str, Any] = {}
    if api_key:
        kwargs["api_key"] = api_key
    if base_url:
        kwargs["base_url"] = base_url
    client = CertiSigmaClient(**kwargs)
    try:
        try:
            result = client.update_metadata(
                attestation_id,
                source=source,
                extra_data=extra if extra else None,
                client_encrypted=client_encrypted if client_encrypted else None,
            )
            return AnnotationResult(
                attestation_id=str(result.attestation_id),
                success=result.success,
                source=result.source,
                extra_data=result.extra_data,
                client_encrypted=result.client_encrypted,
                deleted=result.deleted,
            )
        except CertiSigmaError as exc:
            return AnnotationResult(
                attestation_id=attestation_id,
                success=False,
                error=str(exc),
            )
    finally:
        client.close()


def delete_annotation(
    attestation_id: str,
    api_key: str | None = None,
    base_url: str | None = None,
) -> AnnotationResult:
    """Soft-delete metadata on an attestation (GDPR right-to-erasure)."""
    from certisigma import CertiSigmaClient, CertiSigmaError

    kwargs: dict[str, Any] = {}
    if api_key:
        kwargs["api_key"] = api_key
    if base_url:
        kwargs["base_url"] = base_url
    client = CertiSigmaClient(**kwargs)
    try:
        try:
            result = client.delete_metadata(attestation_id)
            return AnnotationResult(
                attestation_id=str(result.attestation_id),
                success=result.success,
                deleted=result.deleted,
            )
        except CertiSigmaError as exc:
            return AnnotationResult(
                attestation_id=attestation_id,
                success=False,
                error=str(exc),
            )
    finally:
        client.close()


def decrypt_annotation(
    extra_data: dict[str, Any],
    encryption_key: str | None = None,
) -> dict[str, Any]:
    """Decrypt an encrypted extra_data envelope."""
    from certisigma.crypto import decrypt_metadata, is_encrypted
    if not is_encrypted(extra_data):
        return extra_data
    key = _resolve_encryption_key(encryption_key)
    return decrypt_metadata(extra_data, key)


def _resolve_encryption_key(explicit_key: str | None = None) -> str:
    """Get encryption key from argument or config."""
    from .config import resolve_encryption_key
    return resolve_encryption_key(explicit_key)
