"""
Transparency Log (Rekor) Verifier

Verifies Sigstore Rekor transparency log proofs.
"""

from __future__ import annotations

import base64
import hashlib
import logging
import os
from dataclasses import dataclass
from typing import TYPE_CHECKING, Optional

from receipts.verifiers.verdict import ProofVerdict

if TYPE_CHECKING:
    from receipts.models_v1 import ReceiptV1

logger = logging.getLogger(__name__)


@dataclass
class RekorConfig:
    """Configuration for Rekor verification."""
    server_url: str = "https://rekor.sigstore.dev"
    verify_online: bool = False  # If True, fetch from Rekor API
    # In production, you'd also have:
    # rekor_public_key: bytes  # For verifying signed tree heads


def _load_rekor_config() -> RekorConfig:
    """Load Rekor configuration from environment."""
    return RekorConfig(
        server_url=os.environ.get("LOOM_REKOR_SERVER", "https://rekor.sigstore.dev"),
        verify_online=os.environ.get("LOOM_REKOR_VERIFY_ONLINE", "0") == "1",
    )


def _verify_merkle_path(
    leaf_hash: bytes,
    merkle_path: list[str],
    expected_root: Optional[str] = None,
) -> tuple[bool, str]:
    """
    Verify a Merkle audit path.

    Given a leaf hash and sibling hashes, recomputes the root.
    If expected_root is provided, compares against it.

    Returns (is_valid, computed_root_hex)
    """
    current = leaf_hash

    for sibling_b64 in merkle_path:
        try:
            sibling = base64.b64decode(sibling_b64)
        except Exception:
            return False, "invalid_sibling_encoding"

        # Standard Merkle: hash(left || right) with ordering
        # This is a simplified version; real implementation needs
        # to track left/right position
        combined = current + sibling if current < sibling else sibling + current
        current = hashlib.sha256(combined).digest()

    computed_root = current.hex()

    if expected_root:
        return computed_root == expected_root, computed_root

    return True, computed_root


def verify_transparency_log(
    receipt: "ReceiptV1",
    config: Optional[RekorConfig] = None,
) -> ProofVerdict:
    """
    Verify the transparency-log proof.

    Validates:
    1. Entry UUID and log index are present
    2. Merkle path is valid (recomputes root)
    3. integrated_time >= tsa_time (if TSA present)
    4. (Optional) Online verification against Rekor API

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

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

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

    if not isinstance(proof, TransparencyLogProof):
        return ProofVerdict.fail(
            kind="transparency-log",
            reason=f"Invalid proof type: {type(proof).__name__}",
        )

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

    # Validate entry identifiers
    if not proof.entry_uuid:
        return ProofVerdict.fail(
            kind="transparency-log",
            reason="Missing entry_uuid",
        )

    if proof.log_index < 0:
        return ProofVerdict.fail(
            kind="transparency-log",
            reason=f"Invalid log_index: {proof.log_index}",
        )

    # Get content digest for Merkle verification
    digest_proof = receipt.get_proof("content-digest")
    if digest_proof is None or not isinstance(digest_proof, ContentDigestProof):
        return ProofVerdict.fail(
            kind="transparency-log",
            reason="No content-digest for Merkle verification",
        )

    # Decode content digest as leaf
    try:
        leaf_hash = base64.b64decode(digest_proof.value)
    except Exception as e:
        return ProofVerdict.fail(
            kind="transparency-log",
            reason=f"Invalid content digest encoding: {e}",
        )

    # Verify Merkle path (if present)
    if proof.merkle_path:
        is_valid, computed_root = _verify_merkle_path(
            leaf_hash,
            proof.merkle_path,
        )
        if not is_valid:
            return ProofVerdict.fail(
                kind="transparency-log",
                reason=f"Merkle path verification failed: {computed_root}",
            )

    # Check temporal ordering: integrated_time >= tsa_time (if TSA present)
    from receipts.models_v1 import TsaRfc3161Proof
    tsa_proof = receipt.get_proof("tsa-rfc3161")
    if tsa_proof and isinstance(tsa_proof, TsaRfc3161Proof):
        if proof.integrated_time < tsa_proof.tsa_time:
            return ProofVerdict.fail(
                kind="transparency-log",
                reason="Rekor integration time precedes TSA time (temporal violation)",
                details={
                    "integrated_time": proof.integrated_time.isoformat(),
                    "tsa_time": tsa_proof.tsa_time.isoformat(),
                },
            )

    # Online verification (optional)
    if config.verify_online:
        # TODO: Implement Rekor API call
        # - GET /api/v1/log/entries/{entry_uuid}
        # - Verify inclusion proof
        # - Verify signed tree head
        logger.info(f"Online Rekor verification not implemented (uuid={proof.entry_uuid})")

    return ProofVerdict.ok(
        kind="transparency-log",
        reason=f"Transparency log verified (log={proof.log}, idx={proof.log_index})",
    )
