"""Caller-held row-bound canonical registration capability."""
from __future__ import annotations

import hashlib
import json
from dataclasses import dataclass

from checkin_cli.weekly_operations import WeeklyOperationsConflict
from checkin_cli.weekly_operations_canonical_snapshot import CanonicalCheckinCustomerBinding


@dataclass(frozen=True, slots=True)
class RegisteredCanonicalCheckinCustomerBinding:
    canonical_binding: CanonicalCheckinCustomerBinding
    registration_row_digest: str
    authority_binding_digest: str
    authority_marker_digest: str
    registry_binding_digest: str
    binding_digest: str

    def __post_init__(self) -> None:
        values = (
            self.registration_row_digest, self.authority_binding_digest,
            self.authority_marker_digest, self.registry_binding_digest,
            self.binding_digest,
        )
        if any(len(value) != 64 for value in values) or self.binding_digest != registered_binding_digest(self):
            raise WeeklyOperationsConflict("registered canonical binding digest drift")


def _payload(
    canonical: CanonicalCheckinCustomerBinding, row_digest: str,
    authority_digest: str, marker_digest: str, registry_digest: str,
) -> bytes:
    value = {
        "canonical_binding_digest": canonical.binding_digest,
        "registration_row_digest": row_digest,
        "authority_binding_digest": authority_digest,
        "authority_marker_digest": marker_digest,
        "registry_binding_digest": registry_digest,
    }
    return json.dumps(value, sort_keys=True, separators=(",", ":")).encode()


def registered_binding_digest(binding: RegisteredCanonicalCheckinCustomerBinding) -> str:
    return hashlib.sha256(_payload(binding.canonical_binding, binding.registration_row_digest, binding.authority_binding_digest, binding.authority_marker_digest, binding.registry_binding_digest)).hexdigest()


def create_registered_binding(
    canonical: CanonicalCheckinCustomerBinding, row_digest: str,
    authority_digest: str, marker_digest: str, registry_digest: str,
) -> RegisteredCanonicalCheckinCustomerBinding:
    digest = hashlib.sha256(
        _payload(canonical, row_digest, authority_digest, marker_digest, registry_digest)
    ).hexdigest()
    return RegisteredCanonicalCheckinCustomerBinding(
        canonical, row_digest, authority_digest, marker_digest, registry_digest, digest
    )
