from .storage import LedgerStorage
from typing import List, Dict, Any, Optional
from .block import Block
from .crypto import sign_block_data, verify_block_signature
import time
import hashlib
import json
from pathlib import Path
import threading

class BlockchainLedger:
    def __init__(self, storage_dir: Optional[Path] = None):
        self._storage = LedgerStorage(storage_dir=storage_dir)
        self._lock = threading.Lock()
        self.chain: List[Block] = self._storage.load()

        if not self.chain:
            self._create_genesis_block()
            self._persist()
        else:
            # ✅ Verify integrity on load
            if not self.verify_integrity():
                 print("⚠️ Blockchain integrity verification failed! Attempting to resolve...")
                 self.handle_fork(self.chain)

    def _persist(self):
        self._storage.save(self.chain)

    def _create_genesis_block(self):
        genesis_block = Block(
            index=0,
            previous_hash="0",
            data={"event_type": "GENESIS"}
        )
        # Sign genesis
        genesis_block.signature = sign_block_data(genesis_block._get_signable_content())
        genesis_block.hash = genesis_block.calculate_hash()

        self.chain.append(genesis_block)

    def add_block(self, data: Dict[str, Any]) -> Block:
        with self._lock:
            last_block = self.chain[-1]

            block = Block(
                index=last_block.index + 1,
                previous_hash=last_block.hash,
                data=data
            )

            # ✅ Sign block
            block.signature = sign_block_data(block._get_signable_content())
            block.hash = block.calculate_hash()

            self.chain.append(block)
            self._persist()
            return block

    def verify_integrity(self) -> bool:
        """Verify the entire blockchain's integrity"""
        with self._lock:
            for i in range(1, len(self.chain)):
                current = self.chain[i]
                previous = self.chain[i-1]

                # 1. Check index
                if current.index != previous.index + 1:
                    return False

                # 2. Check hash link
                if current.previous_hash != previous.hash:
                    return False

                # 3. Re-calculate and check current hash
                if current.hash != current.calculate_hash():
                    return False

                # 4. Verify signature
                if not current.verify_signature():
                    return False

            return True

    def handle_fork(self, new_chain: List[Block]):
        """Simple fork resolution: Keep the longest valid chain"""
        if len(new_chain) > len(self.chain):
            # Verify new chain
            is_valid = True
            for i in range(1, len(new_chain)):
                if new_chain[i].previous_hash != new_chain[i-1].hash:
                    is_valid = False
                    break

            if is_valid:
                self.chain = new_chain
                self._persist()
                return True
        return False

    def get_chain(self) -> List[Block]:
        return self.chain

    def log_event(self, event_type, actor_type, actor_id, data, cause_id=None):
        event_data = {
            "event_type": event_type,
            "actor_type": actor_type,
            "actor_id": actor_id,
            "timestamp": time.time(),
            "data": data,
            "cause_id": cause_id
        }
        self.add_block(event_data)
