"""Compute request identity for artifact deduplication and caching.

Combines upstream instance identity, prefix, tool name, and
RFC 8785 canonical arguments into a deterministic request key.
Exports ``RequestIdentity`` as a frozen dataclass and the
``compute_request_identity`` helper function.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from sift_gateway.canon.rfc8785 import canonical_bytes, coerce_floats
from sift_gateway.util.hashing import request_key as compute_request_key
from sift_gateway.util.hashing import sha256_hex


@dataclass(frozen=True)
class RequestIdentity:
    """Computed identity for a tool call request.

    Encapsulates the sha256-based request key together with
    the constituent parts used to derive it, enabling both
    cache lookups and diagnostic logging.

    Attributes:
        request_key: SHA-256 hex digest of the full identity.
        request_args_hash: SHA-256 hex digest of canonical args.
        request_args_prefix: First N chars of canonical args
            (capped at REQUEST_ARGS_PREFIX_CAP) for debugging.
        upstream_instance_id: Identity of the upstream server.
        prefix: Tool namespace prefix.
        tool_name: Name of the upstream tool invoked.
        canonical_args: Raw RFC 8785 canonical arg bytes.
        REQUEST_ARGS_PREFIX_CAP: Maximum length of the
            request_args_prefix field (class constant).
    """

    request_key: str  # sha256 hex of full identity
    request_args_hash: str  # sha256 hex of canonical args
    request_args_prefix: (
        str  # first N chars of canonical args for debugging (capped)
    )
    upstream_instance_id: str
    prefix: str
    tool_name: str
    canonical_args: bytes  # the canonical arg bytes

    REQUEST_ARGS_PREFIX_CAP = 200


def compute_request_identity(
    *,
    upstream_instance_id: str,
    prefix: str,
    tool_name: str,
    forwarded_args: dict[str, Any],
) -> RequestIdentity:
    """Compute request_key from upstream identity and tool args.

    Derives a deterministic SHA-256 request key from the
    upstream instance, prefix, tool name, and RFC 8785
    canonical arguments.

    Args:
        upstream_instance_id: Identity of the upstream server.
        prefix: Tool namespace prefix.
        tool_name: Name of the upstream tool.
        forwarded_args: Arguments dict to canonicalize.

    Returns:
        A RequestIdentity with the computed request key and
        constituent parts.
    """
    canonical_args = canonical_bytes(coerce_floats(forwarded_args))
    args_hash = sha256_hex(canonical_args)

    # Compute request key per spec
    req_key = compute_request_key(
        upstream_instance_id,
        prefix,
        tool_name,
        canonical_args,
    )

    # Capped prefix for debugging
    args_text = canonical_args.decode("utf-8", errors="replace")
    args_prefix = args_text[: RequestIdentity.REQUEST_ARGS_PREFIX_CAP]

    return RequestIdentity(
        request_key=req_key,
        request_args_hash=args_hash,
        request_args_prefix=args_prefix,
        upstream_instance_id=upstream_instance_id,
        prefix=prefix,
        tool_name=tool_name,
        canonical_args=canonical_args,
    )
