"""
Vision Domain Receipts

Includes:
- VisionReceipt: For every visual ingestion event
- VisionConfig: Configuration for multi-fidelity vision

Part of Vision Organ: Multi-fidelity perception for Shadow Self
"""

import time
import logging
from typing import Dict, Any, Optional, List
from dataclasses import dataclass
from datetime import datetime
from enum import Enum

from receipts.base import BaseReceipt, Domain
from receipts.compat.pyd import Field
import uuid
from tools.proofkit import ProofKit

# Initialize ProofKit for vision receipts
proofkit = ProofKit()
logger = logging.getLogger(__name__)


class VisionMode(Enum):
    """Four levels of visual fidelity for the Vision Organ."""

    SEMANTIC = "semantic"  # Layer A: Text/structure only
    LOW_RES = "low_res"    # Layer B: Downsampled raster
    FOVEA = "fovea"        # Layer C: High-res crop
    FULL = "full"          # Layer D: Complete capture


@dataclass
class VisionConfig:
    """Configuration for multi-fidelity vision system."""

    # Default behavior
    default_mode: VisionMode = VisionMode.SEMANTIC
    allow_full_mode: bool = True
    max_full_mode_minutes: int = 30

    # Layer B: Low-res settings
    low_res_target: tuple[int, int] = (256, 160)
    low_res_grayscale: bool = True
    low_res_edge_detect: bool = False

    # Layer C: Foveal settings
    fovea_crop_size: tuple[int, int] = (512, 512)
    fovea_max_crops_per_minute: int = 10

    # Layer D: Full settings
    full_max_fps: float = 1.0
    full_privacy_warning_required: bool = True

    # Constitutional
    require_vision_receipts: bool = True
    emergency_mode_only_semantic: bool = True


class VisionReceipt(BaseReceipt):
    """Pydantic receipt capturing every visual ingestion event."""

    receipt_type: str = Field(default="VisionReceipt", frozen=True)

    # Vision specifics
    vision_mode: str
    reason: str
    app_context: str
    bbox: Optional[List[int]] = None

    capture_ms: int = 0
    data_size_bytes: int = 0

    privacy_safe: bool = True
    consent_obtained: bool = True
    profile: str = "enterprise"
    receipt_mode: str = "signed"
    retention_days: Optional[int] = None
    encryption_required: bool = False

    attestation: Dict[str, Any] = Field(default_factory=dict)

    def sign(self, key: bytes, algorithm: str = "hmac-sha256") -> None:
        """
        Sign this vision receipt with Proof Rails vNext attestation.

        Args:
            key: Signing key
            algorithm: Signing algorithm ("hmac-sha256" or "ed25519")
        """
        if self.receipt_mode != "signed":
            logger.debug(f"Skipping signature for VisionReceipt {self.receipt_id} (receipt_mode: {self.receipt_mode})")
            return

        try:
            # Create signed receipt data
            signed_receipt = proofkit.sign_receipt(
                self.to_dict(),
                key,
                algorithm
            )
            # Extract attestation block
            self.attestation = signed_receipt.get("attestation", {})
            logger.info(f"Signed VisionReceipt: {self.receipt_id}")
        except Exception as e:
            logger.error(f"Failed to sign VisionReceipt {self.receipt_id}: {e}")
            # Continue without attestation rather than failing

    def verify_signature(self, key: bytes, algorithm: str = "hmac-sha256") -> bool:
        """
        Verify the cryptographic signature of this vision receipt.

        Args:
            key: Verification key
            algorithm: Algorithm used for signing

        Returns:
            True if signature is valid
        """
        if not self.attestation:
            return False

        try:
            return proofkit.verify_receipt_signature(
                self.to_dict(),
                key,
                algorithm
            )
        except Exception as e:
            logger.error(f"Failed to verify VisionReceipt {self.receipt_id}: {e}")
            return False

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for serialization."""
        data = self.model_dump()
        if self.attestation:
            data['attestation'] = self.attestation
        return data


# Convenience functions for creating vision receipts

def create_vision_receipt(
    vision_mode: VisionMode,
    reason: str,
    app_context: str,
    bbox: Optional[List[int]] = None,
    capture_ms: int = 0,
    data_size_bytes: int = 0,
    sign_key: Optional[bytes] = None,
    sign_algorithm: str = "hmac-sha256",
    profile: str = "enterprise",
    receipt_mode: str = "signed",
    retention_days: Optional[int] = None,
    encryption_required: bool = False,
    **kwargs
) -> VisionReceipt:
    """
    Create a VisionReceipt for a visual capture event.

    Args:
        vision_mode: Level of visual fidelity used
        reason: Why this fidelity level was chosen
        app_context: Active application during capture
        bbox: Bounding box for foveal captures [x,y,w,h]
        capture_ms: Time taken to capture (performance metric)
        data_size_bytes: Size of captured data (performance metric)
        sign_key: Optional cryptographic key for signing
        sign_algorithm: Signing algorithm ("hmac-sha256" or "ed25519")
        **kwargs: Additional fields

    Returns:
        VisionReceipt instance, signed if key provided
    """
    receipt = VisionReceipt(
        receipt_id=str(uuid.uuid4()),
        domain=Domain.CLINICAL.value,
        vision_mode=vision_mode.value,
        reason=reason,
        app_context=app_context,
        bbox=bbox,
        capture_ms=capture_ms,
        data_size_bytes=data_size_bytes,
        profile=profile,
        receipt_mode=receipt_mode,
        retention_days=retention_days,
        encryption_required=encryption_required,
        **kwargs
    )

    # Sign if key provided
    if sign_key and receipt_mode == "signed":
        receipt.sign(sign_key, sign_algorithm)

    return receipt


def emit_vision_receipt(receipt: VisionReceipt) -> str:
    """
    Emit a VisionReceipt to the ledger.
    Returns the receipt ID.
    """
    # This would integrate with the existing receipt writer
    # For now, just return a mock ID
    receipt_id = f"vision_{int(time.time())}_{hash(str(receipt)) % 10000}"
    logger.info(f"Emitted VisionReceipt: {receipt_id}")
    return receipt_id


# Example usage

def example_vision_receipt():
    """Example of creating and emitting a VisionReceipt."""
    # Example signing key (in production, use proper key management)
    sign_key = b"example-key-32-bytes-for-vision!!!"

    receipt = create_vision_receipt(
        vision_mode=VisionMode.FOVEA,
        reason="need to read tiny label on button",
        app_context="Safari",
        bbox=[100, 200, 150, 230],
        capture_ms=45,
        data_size_bytes=15360,
        privacy_safe=True,
        consent_obtained=True,
        sign_key=sign_key  # Enable cryptographic signing
    )

    # Verify signature works
    is_valid = receipt.verify_signature(sign_key)
    print(f"VisionReceipt signature valid: {is_valid}")

    receipt_id = emit_vision_receipt(receipt)
    return receipt_id


if __name__ == "__main__":
    # Run example
    receipt_id = example_vision_receipt()
    print(f"Created VisionReceipt: {receipt_id}")
