"""Build resolution lock payloads for stage 070."""

from datetime import UTC, datetime
from typing import Any, Protocol

from accountable_record.stage_070_resolution.base import constants
from accountable_record.stage_070_resolution.model import ResolutionPolicy

__all__ = [
    "DEFAULT_RESOLUTION_POLICY",
    "GeneratedElementLike",
    "build_element_lock_payload",
]

DEFAULT_RESOLUTION_POLICY = ResolutionPolicy(
    one_major_version_per_identity_per_graph=True,
    range_conflicts_are_errors=True,
)


class GeneratedElementLike(Protocol):
    """Structural input needed to build one element lock entry."""

    @property
    def compact_id(self) -> str:
        """Return the generated element compact id."""
        ...

    @property
    def digest(self) -> str:
        """Return the generated element canonical digest."""
        ...


def build_element_lock_payload(
    generated_records: tuple[GeneratedElementLike, ...],
) -> dict[str, Any]:
    """Build the element lock payload from generated artifact records."""
    return {
        constants.LOCK_KEY_SCHEMA: constants.ELEMENT_LOCK_SCHEMA_TAG,
        constants.LOCK_KEY_RESOLVED_AT: _resolved_at_utc(),
        constants.LOCK_KEY_RESOLUTION_POLICY: _resolution_policy_payload(
            DEFAULT_RESOLUTION_POLICY
        ),
        constants.LOCK_KEY_PACKAGES: [],
        constants.LOCK_KEY_ELEMENTS: [
            _element_payload(record) for record in generated_records
        ],
    }


def _element_payload(record: GeneratedElementLike) -> dict[str, Any]:
    """Return one element lock entry from a generated element record."""
    return {
        constants.ELEMENT_KEY_COMPACT_ID: record.compact_id,
        constants.ELEMENT_KEY_VERSION: "0.1.0",
        constants.ELEMENT_KEY_INCLUDED_BY: [],
        constants.ELEMENT_KEY_DIGEST_ALGORITHM: constants.DIGEST_ALGORITHM_SHA256,
        constants.ELEMENT_KEY_DIGEST_TARGET: (
            constants.DIGEST_TARGET_CANONICAL_GENERATED_JSON
        ),
        constants.ELEMENT_KEY_DIGEST: record.digest,
    }


def _resolution_policy_payload(policy: ResolutionPolicy) -> dict[str, bool]:
    """Return the JSON payload for a resolution policy."""
    return {
        constants.POLICY_ONE_MAJOR_VERSION_PER_IDENTITY_PER_GRAPH: (
            policy.one_major_version_per_identity_per_graph
        ),
        constants.POLICY_RANGE_CONFLICTS_ARE_ERRORS: (
            policy.range_conflicts_are_errors
        ),
    }


def _resolved_at_utc() -> str:
    """Return the lock resolution timestamp in UTC ISO-8601 form."""
    return datetime.now(UTC).replace(microsecond=0).isoformat()
