"""Environment-only configuration for authenticated Agent result writeback."""

from __future__ import annotations

import base64
import binascii
import os
from dataclasses import dataclass
from typing import Mapping, Optional

from arr_ingestion.contracts import OPAQUE_ID_RE
from arr_processing.errors import ProcessingError
from arr_processing.signatures import SignedResultCodec


@dataclass(frozen=True)
class ResultVerificationConfig:
    key_id: str
    secret: bytes
    max_age_seconds: int = 600

    @classmethod
    def from_environment(
        cls,
        environment: Optional[Mapping[str, str]] = None,
    ) -> "ResultVerificationConfig":
        values = environment if environment is not None else os.environ
        key_id = str(values.get("ARR_AGENT_RESULT_HMAC_KEY_ID", "")).strip()
        encoded = str(values.get("ARR_AGENT_RESULT_HMAC_KEY_B64", "")).strip()
        age_text = str(values.get("ARR_AGENT_RESULT_MAX_AGE_SECONDS", "600")).strip()
        if not OPAQUE_ID_RE.fullmatch(key_id):
            raise ProcessingError(
                "PROCESSING_SIGNATURE_CONFIG_MISSING",
                "Agent result signing key identifier is missing",
            )
        try:
            secret = base64.b64decode(encoded, validate=True)
            max_age = int(age_text)
        except (binascii.Error, ValueError):
            raise ProcessingError(
                "PROCESSING_SIGNATURE_CONFIG_INVALID",
                "Agent result signing configuration is invalid",
            ) from None
        if len(secret) < 32 or not 1 <= max_age <= 3600:
            raise ProcessingError(
                "PROCESSING_SIGNATURE_CONFIG_INVALID",
                "Agent result signing configuration is invalid",
            )
        return cls(key_id=key_id, secret=secret, max_age_seconds=max_age)

    def verifier(self) -> SignedResultCodec:
        return SignedResultCodec(
            {self.key_id: self.secret},
            max_age_seconds=self.max_age_seconds,
        )

    def signer(self) -> SignedResultCodec:
        return SignedResultCodec(
            {self.key_id: self.secret},
            signing_key_id=self.key_id,
            max_age_seconds=self.max_age_seconds,
        )
