"""
TSA RFC 3161 Verifier

Verifies RFC 3161 Time Stamp Authority tokens.
"""

from __future__ import annotations

import base64
import logging
import os
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, List, Optional

from receipts.verifiers.verdict import ProofVerdict

if TYPE_CHECKING:
    from receipts.models_v1 import ReceiptV1

logger = logging.getLogger(__name__)


@dataclass
class TsaConfig:
    """Configuration for TSA verification."""
    trusted_tsa_ids: List[str] = field(default_factory=list)
    # In production, you'd also have:
    # tsa_root_certs: Dict[str, bytes]  # tsa_id -> root cert


def _load_tsa_config() -> TsaConfig:
    """Load TSA configuration from environment."""
    trusted = os.environ.get("LOOM_TRUSTED_TSA_IDS", "").split(",")
    trusted = [t.strip() for t in trusted if t.strip()]
    return TsaConfig(trusted_tsa_ids=trusted)


def verify_tsa_rfc3161(
    receipt: "ReceiptV1",
    config: Optional[TsaConfig] = None,
) -> ProofVerdict:
    """
    Verify the tsa-rfc3161 proof.

    Validates:
    1. TSA ID is trusted (if trust list configured)
    2. Token structure is valid
    3. Token hash matches content digest
    4. tsa_time >= receipt_time

    Note: Full cryptographic verification of the TSA signature requires
    the TSA's root certificate chain. This implementation does structural
    validation; extend with rfc3161-client for full verification.

    Args:
        receipt: The ReceiptV1 to verify
        config: Optional TSA configuration

    Returns:
        ProofVerdict with ok/fail/skipped status
    """
    from receipts.models_v1 import TsaRfc3161Proof, ContentDigestProof

    # Get the tsa-rfc3161 proof
    proof = receipt.get_proof("tsa-rfc3161")
    if proof is None:
        return ProofVerdict.fail(
            kind="tsa-rfc3161",
            reason="No tsa-rfc3161 proof present",
        )

    if not isinstance(proof, TsaRfc3161Proof):
        return ProofVerdict.fail(
            kind="tsa-rfc3161",
            reason=f"Invalid proof type: {type(proof).__name__}",
        )

    # Load config
    if config is None:
        config = _load_tsa_config()

    # Check trusted TSA
    if config.trusted_tsa_ids and proof.tsa_id not in config.trusted_tsa_ids:
        return ProofVerdict.fail(
            kind="tsa-rfc3161",
            reason=f"Untrusted TSA: {proof.tsa_id}",
            details={"trusted": config.trusted_tsa_ids},
        )

    # Validate token is base64
    try:
        token_bytes = base64.b64decode(proof.token)
        if len(token_bytes) < 32:
            return ProofVerdict.fail(
                kind="tsa-rfc3161",
                reason="Token too short (likely malformed)",
            )
    except Exception as e:
        return ProofVerdict.fail(
            kind="tsa-rfc3161",
            reason=f"Invalid token encoding: {e}",
        )

    # Check temporal ordering: tsa_time >= receipt_time
    if proof.tsa_time < receipt.envelope.receipt_time:
        return ProofVerdict.fail(
            kind="tsa-rfc3161",
            reason="TSA time precedes receipt time (temporal violation)",
            details={
                "tsa_time": proof.tsa_time.isoformat(),
                "receipt_time": receipt.envelope.receipt_time.isoformat(),
            },
        )

    # Get content digest for hash comparison
    digest_proof = receipt.get_proof("content-digest")
    if digest_proof is None or not isinstance(digest_proof, ContentDigestProof):
        return ProofVerdict.fail(
            kind="tsa-rfc3161",
            reason="No content-digest to verify TSA token against",
        )

    # In a full implementation, you'd verify:
    # 1. Parse the ASN.1 TimeStampToken
    # 2. Extract the message imprint hash
    # 3. Compare to content digest
    # 4. Verify TSA signature chain
    #
    # For now, we do structural validation only.
    # TODO: Integrate rfc3161-client for full verification

    return ProofVerdict.ok(
        kind="tsa-rfc3161",
        reason=f"TSA token validated (tsa={proof.tsa_id}, time={proof.tsa_time.isoformat()})",
    )
