import hashlib
import hmac
import json
import uuid
from collections.abc import Iterable

from .models import AuditEvent


def compute_audit_hash(*, previous_hash: bytes | None, sequence: int, event_id: uuid.UUID,
                       workspace_id: uuid.UUID, actor_id: uuid.UUID, event_type: str,
                       request_id: str | None, data: dict) -> bytes:
    canonical_data = json.dumps(data, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
    material = (
        f"{previous_hash.hex() if previous_hash else ''}|{sequence}|{event_id}|{workspace_id}|"
        f"{actor_id}|{event_type}|{request_id or ''}|{canonical_data}"
    )
    return hashlib.sha256(material.encode("utf-8")).digest()


def verify_audit_chain(events: Iterable[AuditEvent], expected_head: bytes | None) -> bool:
    previous: bytes | None = None
    expected_sequence = 1
    for event in sorted(events, key=lambda item: item.sequence):
        if event.sequence != expected_sequence or event.previous_hash != previous:
            return False
        computed = compute_audit_hash(
            previous_hash=previous,
            sequence=event.sequence,
            event_id=event.id,
            workspace_id=event.workspace_id,
            actor_id=event.actor_id,
            event_type=event.event_type,
            request_id=event.request_id,
            data=event.data,
        )
        if not hmac.compare_digest(computed, event.event_hash):
            return False
        previous = event.event_hash
        expected_sequence += 1
    return hmac.compare_digest(previous or b"", expected_head or b"")
