import hashlib
import json
import threading
import time
import uuid
from typing import Any, Dict, List, Optional
from .crypto import Signature


class Block:
    """
    Represents a single immutable block in the ledger.
    """
    def __init__(
        self,
        index: int,
        previous_hash: str,
        data: Dict[str, Any],
        merkle_root: Optional[str] = None,
        signature: Optional[Signature] = None
    ):
        self.index = index
        self.timestamp = time.time()
        self.data = data
        self.previous_hash = previous_hash
        self.merkle_root = merkle_root or ""
        self.signature = signature
        self.hash = self.calculate_hash()

    def _get_signable_content(self) -> str:
        """Standardized string representation for hashing and signing"""
        return json.dumps({
            "index": self.index,
            "timestamp": self.timestamp,
            "data": self.data,
            "previous_hash": self.previous_hash,
            "merkle_root": self.merkle_root
        }, sort_keys=True)

    def calculate_hash(self) -> str:
        """Calculate block hash including Merkle root"""
        return hashlib.sha256(self._get_signable_content().encode()).hexdigest()

    def to_dict(self) -> Dict:
        """Convert block to dictionary for storage"""
        return {
            "index": self.index,
            "timestamp": self.timestamp,
            "data": self.data,
            "previous_hash": self.previous_hash,
            "merkle_root": self.merkle_root,
            "signature": {
                "signature": self.signature.signature,
                "public_key": self.signature.public_key
            } if self.signature else None,
            "hash": self.hash
        }

    @staticmethod
    def from_dict(data: Dict) -> 'Block':
        """Create block from dictionary"""
        signature = None
        if data.get("signature"):
            signature = Signature(
                signature=data["signature"]["signature"],
                public_key=data["signature"]["public_key"]
            )

        block = Block(
            index=data["index"],
            previous_hash=data["previous_hash"],
            data=data["data"],
            merkle_root=data.get("merkle_root", ""),
            signature=signature
        )
        block.timestamp = data["timestamp"]
        block.hash = data["hash"]
        return block

    def verify_signature(self) -> bool:
        """Verify block signature"""
        if not self.signature:
            return False

        from altrus.core.ledger.crypto import verify_block_signature
        return verify_block_signature(self._get_signable_content(), self.signature)
