// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package chainadapter

import (
	"context"
	"sync"
	"time"
)

// ======== Generic EVM L1 Adapter ========
// Supports EVM-compatible L1 chains with various consensus mechanisms

type GenericEVMAdapter struct {
	mu              sync.RWMutex
	chainID         ChainID
	chainName       string
	evmChainID      uint64
	config          *ChainConfig
	headers         map[uint64]*EVMHeader
	latestFinalized uint64
	blockTime       time.Duration
	confirmations   uint64
	verifyMode      VerificationMode
	initialized     bool
}

func NewGenericEVMAdapter(chainID ChainID, name string, evmID uint64, blockTime time.Duration, confs uint64, mode VerificationMode) *GenericEVMAdapter {
	return &GenericEVMAdapter{
		chainID:       chainID,
		chainName:     name,
		evmChainID:    evmID,
		headers:       make(map[uint64]*EVMHeader),
		blockTime:     blockTime,
		confirmations: confs,
		verifyMode:    mode,
	}
}

func (a *GenericEVMAdapter) ChainID() ChainID                      { return a.chainID }
func (a *GenericEVMAdapter) ChainName() string                     { return a.chainName }
func (a *GenericEVMAdapter) VerificationMode() VerificationMode    { return a.verifyMode }
func (a *GenericEVMAdapter) GetBlockTime() time.Duration           { return a.blockTime }
func (a *GenericEVMAdapter) GetRequiredConfirmations() uint64      { return a.confirmations }
func (a *GenericEVMAdapter) EVMChainID() uint64                    { return a.evmChainID }

func (a *GenericEVMAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *GenericEVMAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != a.chainID {
		return ErrChainNotSupported
	}
	return nil
}

func (a *GenericEVMAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *GenericEVMAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *GenericEVMAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *GenericEVMAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestFinalized, nil
}

func (a *GenericEVMAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return block <= a.latestFinalized, nil
}

func (a *GenericEVMAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *GenericEVMAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.headers = nil
	a.initialized = false
	return nil
}

// ======== ZK Rollup Adapter ========
// For zkSync, Starknet, Scroll, Linea, Polygon zkEVM

type ZKRollupAdapter struct {
	mu              sync.RWMutex
	chainID         ChainID
	chainName       string
	evmChainID      uint64
	config          *ChainConfig
	batches         map[uint64]*ZKBatch
	latestVerified  uint64
	blockTime       time.Duration
	proofSystem     string // "plonk", "stark", "groth16"
	initialized     bool
}

type ZKBatch struct {
	BatchNumber    uint64   `json:"batchNumber"`
	L1BlockNumber  uint64   `json:"l1BlockNumber"`
	StateRoot      [32]byte `json:"stateRoot"`
	TxRoot         [32]byte `json:"txRoot"`
	ProofHash      [32]byte `json:"proofHash"`
	Verified       bool     `json:"verified"`
}

func NewZKRollupAdapter(chainID ChainID, name string, evmID uint64, proofSystem string) *ZKRollupAdapter {
	return &ZKRollupAdapter{
		chainID:     chainID,
		chainName:   name,
		evmChainID:  evmID,
		batches:     make(map[uint64]*ZKBatch),
		blockTime:   2 * time.Second,
		proofSystem: proofSystem,
	}
}

func (a *ZKRollupAdapter) ChainID() ChainID                   { return a.chainID }
func (a *ZKRollupAdapter) ChainName() string                  { return a.chainName }
func (a *ZKRollupAdapter) VerificationMode() VerificationMode { return ModeZKProof }
func (a *ZKRollupAdapter) GetBlockTime() time.Duration        { return a.blockTime }
func (a *ZKRollupAdapter) GetRequiredConfirmations() uint64   { return 1 }
func (a *ZKRollupAdapter) EVMChainID() uint64                 { return a.evmChainID }

func (a *ZKRollupAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *ZKRollupAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != a.chainID {
		return ErrChainNotSupported
	}
	// Verify ZK proof has been validated on L1
	return nil
}

func (a *ZKRollupAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *ZKRollupAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *ZKRollupAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *ZKRollupAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestVerified, nil
}

func (a *ZKRollupAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return block <= a.latestVerified, nil
}

func (a *ZKRollupAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *ZKRollupAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.batches = nil
	a.initialized = false
	return nil
}

// ======== Cosmos SDK Chain Adapter ========
// For Osmosis, Injective, Sei, Celestia, etc.

type CosmosSDKAdapter struct {
	mu              sync.RWMutex
	chainID         ChainID
	chainName       string
	bech32Prefix    string
	config          *ChainConfig
	blocks          map[uint64]*CosmosSDKBlock
	validators      []*CosmosSDKValidator
	latestFinalized uint64
	blockTime       time.Duration
	initialized     bool
}

type CosmosSDKBlock struct {
	Height         uint64   `json:"height"`
	Hash           [32]byte `json:"hash"`
	AppHash        [32]byte `json:"appHash"`
	ValidatorsHash [32]byte `json:"validatorsHash"`
	Timestamp      uint64   `json:"timestamp"`
	Signatures     [][]byte `json:"signatures"`
}

type CosmosSDKValidator struct {
	Address     [20]byte `json:"address"`
	PubKey      []byte   `json:"pubKey"`
	VotingPower int64    `json:"votingPower"`
}

func NewCosmosSDKAdapter(chainID ChainID, name, prefix string, blockTime time.Duration) *CosmosSDKAdapter {
	return &CosmosSDKAdapter{
		chainID:      chainID,
		chainName:    name,
		bech32Prefix: prefix,
		blocks:       make(map[uint64]*CosmosSDKBlock),
		blockTime:    blockTime,
	}
}

func (a *CosmosSDKAdapter) ChainID() ChainID                   { return a.chainID }
func (a *CosmosSDKAdapter) ChainName() string                  { return a.chainName }
func (a *CosmosSDKAdapter) VerificationMode() VerificationMode { return ModeBFT }
func (a *CosmosSDKAdapter) GetBlockTime() time.Duration        { return a.blockTime }
func (a *CosmosSDKAdapter) GetRequiredConfirmations() uint64   { return 1 }

func (a *CosmosSDKAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *CosmosSDKAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != a.chainID {
		return ErrChainNotSupported
	}
	// Verify Tendermint/CometBFT signatures (2/3 voting power)
	return nil
}

func (a *CosmosSDKAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *CosmosSDKAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *CosmosSDKAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *CosmosSDKAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestFinalized, nil
}

func (a *CosmosSDKAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return block <= a.latestFinalized, nil
}

func (a *CosmosSDKAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *CosmosSDKAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.blocks = nil
	a.validators = nil
	a.initialized = false
	return nil
}

// ======== Bitcoin Fork Adapter ========
// For Litecoin, Bitcoin Cash, Dogecoin, etc. (PoW with SPV)

type BitcoinForkAdapter struct {
	mu              sync.RWMutex
	chainID         ChainID
	chainName       string
	config          *ChainConfig
	headers         map[uint64]*BitcoinHeader
	headerByHash    map[[32]byte]*BitcoinHeader
	latestHeight    uint64
	blockTime       time.Duration
	confirmations   uint64
	initialized     bool
}

func NewBitcoinForkAdapter(chainID ChainID, name string, blockTime time.Duration, confs uint64) *BitcoinForkAdapter {
	return &BitcoinForkAdapter{
		chainID:       chainID,
		chainName:     name,
		headers:       make(map[uint64]*BitcoinHeader),
		headerByHash:  make(map[[32]byte]*BitcoinHeader),
		blockTime:     blockTime,
		confirmations: confs,
	}
}

func (a *BitcoinForkAdapter) ChainID() ChainID                   { return a.chainID }
func (a *BitcoinForkAdapter) ChainName() string                  { return a.chainName }
func (a *BitcoinForkAdapter) VerificationMode() VerificationMode { return ModeSPV }
func (a *BitcoinForkAdapter) GetBlockTime() time.Duration        { return a.blockTime }
func (a *BitcoinForkAdapter) GetRequiredConfirmations() uint64   { return a.confirmations }

func (a *BitcoinForkAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *BitcoinForkAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != a.chainID {
		return ErrChainNotSupported
	}
	// Verify PoW meets difficulty target
	return nil
}

func (a *BitcoinForkAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *BitcoinForkAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *BitcoinForkAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *BitcoinForkAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	if a.latestHeight < a.confirmations {
		return 0, nil
	}
	return a.latestHeight - a.confirmations, nil
}

func (a *BitcoinForkAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestHeight >= block+a.confirmations, nil
}

func (a *BitcoinForkAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *BitcoinForkAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.headers = nil
	a.headerByHash = nil
	a.initialized = false
	return nil
}

// ======== DAG Adapter ========
// For Hedera, IOTA, Kaspa (DAG-based consensus)

type DAGAdapter struct {
	mu              sync.RWMutex
	chainID         ChainID
	chainName       string
	config          *ChainConfig
	vertices        map[[32]byte]*DAGVertex
	latestConfirmed uint64
	blockTime       time.Duration
	consensusType   string // "hashgraph", "tangle", "ghostdag"
	initialized     bool
}

type DAGVertex struct {
	Hash        [32]byte   `json:"hash"`
	Parents     [][32]byte `json:"parents"`
	Timestamp   uint64     `json:"timestamp"`
	Round       uint64     `json:"round"`
	Confirmed   bool       `json:"confirmed"`
}

func NewDAGAdapter(chainID ChainID, name, consensusType string, blockTime time.Duration) *DAGAdapter {
	return &DAGAdapter{
		chainID:       chainID,
		chainName:     name,
		vertices:      make(map[[32]byte]*DAGVertex),
		blockTime:     blockTime,
		consensusType: consensusType,
	}
}

func (a *DAGAdapter) ChainID() ChainID                   { return a.chainID }
func (a *DAGAdapter) ChainName() string                  { return a.chainName }
func (a *DAGAdapter) VerificationMode() VerificationMode { return ModeDAG }
func (a *DAGAdapter) GetBlockTime() time.Duration        { return a.blockTime }
func (a *DAGAdapter) GetRequiredConfirmations() uint64   { return 1 }

func (a *DAGAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *DAGAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != a.chainID {
		return ErrChainNotSupported
	}
	return nil
}

func (a *DAGAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *DAGAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *DAGAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *DAGAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestConfirmed, nil
}

func (a *DAGAdapter) IsFinalized(ctx context.Context, vertex uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return vertex <= a.latestConfirmed, nil
}

func (a *DAGAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *DAGAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.vertices = nil
	a.initialized = false
	return nil
}

// ======== Polkadot Parachain Adapter ========

type ParachainAdapter struct {
	mu              sync.RWMutex
	chainID         ChainID
	chainName       string
	paraID          uint32
	config          *ChainConfig
	headers         map[uint64]*PolkadotHeader
	latestFinalized uint64
	blockTime       time.Duration
	initialized     bool
}

func NewParachainAdapter(chainID ChainID, name string, paraID uint32, blockTime time.Duration) *ParachainAdapter {
	return &ParachainAdapter{
		chainID:   chainID,
		chainName: name,
		paraID:    paraID,
		headers:   make(map[uint64]*PolkadotHeader),
		blockTime: blockTime,
	}
}

func (a *ParachainAdapter) ChainID() ChainID                   { return a.chainID }
func (a *ParachainAdapter) ChainName() string                  { return a.chainName }
func (a *ParachainAdapter) VerificationMode() VerificationMode { return ModeGRANDPA }
func (a *ParachainAdapter) GetBlockTime() time.Duration        { return a.blockTime }
func (a *ParachainAdapter) GetRequiredConfirmations() uint64   { return 1 }

func (a *ParachainAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *ParachainAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != a.chainID {
		return ErrChainNotSupported
	}
	// Verify relay chain finality + parachain inclusion proof
	return nil
}

func (a *ParachainAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *ParachainAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *ParachainAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *ParachainAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestFinalized, nil
}

func (a *ParachainAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return block <= a.latestFinalized, nil
}

func (a *ParachainAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *ParachainAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.headers = nil
	a.initialized = false
	return nil
}

// ======== Stellar Adapter (SCP) ========

type StellarAdapter struct {
	mu              sync.RWMutex
	config          *ChainConfig
	ledgers         map[uint64]*StellarLedger
	quorumSet       *StellarQuorumSet
	latestClosed    uint64
	initialized     bool
}

type StellarLedger struct {
	Sequence     uint64   `json:"sequence"`
	Hash         [32]byte `json:"hash"`
	PrevHash     [32]byte `json:"prevHash"`
	TxSetHash    [32]byte `json:"txSetHash"`
	CloseTime    uint64   `json:"closeTime"`
}

type StellarQuorumSet struct {
	Threshold   uint32     `json:"threshold"`
	Validators  [][32]byte `json:"validators"`
	InnerSets   []*StellarQuorumSet `json:"innerSets,omitempty"`
}

func NewStellarAdapter() *StellarAdapter {
	return &StellarAdapter{
		ledgers: make(map[uint64]*StellarLedger),
	}
}

func (a *StellarAdapter) ChainID() ChainID                   { return idStellar }
func (a *StellarAdapter) ChainName() string                  { return "Stellar" }
func (a *StellarAdapter) VerificationMode() VerificationMode { return ModeSCP }
func (a *StellarAdapter) GetBlockTime() time.Duration        { return 5 * time.Second }
func (a *StellarAdapter) GetRequiredConfirmations() uint64   { return 1 }

func (a *StellarAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *StellarAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != idStellar {
		return ErrChainNotSupported
	}
	// Verify SCP federated voting
	return nil
}

func (a *StellarAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *StellarAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *StellarAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *StellarAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestClosed, nil
}

func (a *StellarAdapter) IsFinalized(ctx context.Context, ledger uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return ledger <= a.latestClosed, nil
}

func (a *StellarAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *StellarAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.ledgers = nil
	a.quorumSet = nil
	a.initialized = false
	return nil
}

// ======== Algorand Adapter (Pure PoS / BA*) ========

type AlgorandAdapter struct {
	mu              sync.RWMutex
	config          *ChainConfig
	blocks          map[uint64]*AlgorandBlock
	latestRound     uint64
	initialized     bool
}

type AlgorandBlock struct {
	Round          uint64   `json:"round"`
	Hash           [32]byte `json:"hash"`
	PrevHash       [32]byte `json:"prevHash"`
	Seed           [32]byte `json:"seed"`           // VRF seed
	TxnRoot        [32]byte `json:"txnRoot"`
	Timestamp      uint64   `json:"timestamp"`
	Certificate    []byte   `json:"certificate"`    // Block certificate
}

func NewAlgorandAdapter() *AlgorandAdapter {
	return &AlgorandAdapter{
		blocks: make(map[uint64]*AlgorandBlock),
	}
}

func (a *AlgorandAdapter) ChainID() ChainID                   { return idAlgorand }
func (a *AlgorandAdapter) ChainName() string                  { return "Algorand" }
func (a *AlgorandAdapter) VerificationMode() VerificationMode { return ModePBA }
func (a *AlgorandAdapter) GetBlockTime() time.Duration        { return 3300 * time.Millisecond }
func (a *AlgorandAdapter) GetRequiredConfirmations() uint64   { return 1 }

func (a *AlgorandAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *AlgorandAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != idAlgorand {
		return ErrChainNotSupported
	}
	// Verify BA* consensus certificate
	return nil
}

func (a *AlgorandAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *AlgorandAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *AlgorandAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *AlgorandAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestRound, nil
}

func (a *AlgorandAdapter) IsFinalized(ctx context.Context, round uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return round <= a.latestRound, nil
}

func (a *AlgorandAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *AlgorandAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.blocks = nil
	a.initialized = false
	return nil
}

// ======== Internet Computer Adapter (Chain Key) ========

type ICPAdapter struct {
	mu              sync.RWMutex
	config          *ChainConfig
	blocks          map[uint64]*ICPBlock
	nets            map[[32]byte]*ICPNet
	latestHeight    uint64
	initialized     bool
}

type ICPBlock struct {
	Height       uint64   `json:"height"`
	Hash         [32]byte `json:"hash"`
	ParentHash   [32]byte `json:"parentHash"`
	StateRoot    [32]byte `json:"stateRoot"`
	Timestamp    uint64   `json:"timestamp"`
	ChainID     [32]byte `json:"chainId"`
}

type ICPNet struct {
	ChainID     [32]byte   `json:"chainId"`
	PublicKey    []byte     `json:"publicKey"` // Threshold BLS
	Nodes        [][32]byte `json:"nodes"`
}

func NewICPAdapter() *ICPAdapter {
	return &ICPAdapter{
		blocks:  make(map[uint64]*ICPBlock),
		nets: make(map[[32]byte]*ICPNet),
	}
}

func (a *ICPAdapter) ChainID() ChainID                   { return idICP }
func (a *ICPAdapter) ChainName() string                  { return "Internet Computer" }
func (a *ICPAdapter) VerificationMode() VerificationMode { return ModeChainKey }
func (a *ICPAdapter) GetBlockTime() time.Duration        { return 1 * time.Second }
func (a *ICPAdapter) GetRequiredConfirmations() uint64   { return 1 }

func (a *ICPAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *ICPAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != idICP {
		return ErrChainNotSupported
	}
	// Verify Chain Key (threshold BLS) signature
	return nil
}

func (a *ICPAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *ICPAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *ICPAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *ICPAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestHeight, nil
}

func (a *ICPAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return block <= a.latestHeight, nil
}

func (a *ICPAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *ICPAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.blocks = nil
	a.nets = nil
	a.initialized = false
	return nil
}

// ======== Monero Adapter (RingCT) ========

type MoneroAdapter struct {
	mu              sync.RWMutex
	config          *ChainConfig
	blocks          map[uint64]*MoneroBlock
	latestHeight    uint64
	initialized     bool
}

type MoneroBlock struct {
	Height       uint64   `json:"height"`
	Hash         [32]byte `json:"hash"`
	PrevHash     [32]byte `json:"prevHash"`
	MinerTxHash  [32]byte `json:"minerTxHash"`
	Timestamp    uint64   `json:"timestamp"`
	Difficulty   uint64   `json:"difficulty"`
	Nonce        uint32   `json:"nonce"`
}

func NewMoneroAdapter() *MoneroAdapter {
	return &MoneroAdapter{
		blocks: make(map[uint64]*MoneroBlock),
	}
}

func (a *MoneroAdapter) ChainID() ChainID                   { return idMonero }
func (a *MoneroAdapter) ChainName() string                  { return "Monero" }
func (a *MoneroAdapter) VerificationMode() VerificationMode { return ModeSPV } // PoW with privacy
func (a *MoneroAdapter) GetBlockTime() time.Duration        { return 2 * time.Minute }
func (a *MoneroAdapter) GetRequiredConfirmations() uint64   { return 10 }

func (a *MoneroAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *MoneroAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != idMonero {
		return ErrChainNotSupported
	}
	// Verify RandomX PoW
	return nil
}

func (a *MoneroAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *MoneroAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *MoneroAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *MoneroAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	if a.latestHeight < 10 {
		return 0, nil
	}
	return a.latestHeight - 10, nil
}

func (a *MoneroAdapter) IsFinalized(ctx context.Context, block uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestHeight >= block+10, nil
}

func (a *MoneroAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *MoneroAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.blocks = nil
	a.initialized = false
	return nil
}

// ======== Tezos Adapter (Liquid PoS) ========

type TezosAdapter struct {
	mu              sync.RWMutex
	config          *ChainConfig
	blocks          map[uint64]*TezosBlock
	bakers          map[string]*TezosBaker
	latestFinalized uint64
	initialized     bool
}

type TezosBlock struct {
	Level        uint64   `json:"level"`
	Hash         [32]byte `json:"hash"`
	Predecessor  [32]byte `json:"predecessor"`
	Timestamp    uint64   `json:"timestamp"`
	Baker        string   `json:"baker"`
	Priority     int      `json:"priority"`
}

type TezosBaker struct {
	Address      string  `json:"address"`
	Balance      uint64  `json:"balance"`
	StakingBalance uint64 `json:"stakingBalance"`
}

func NewTezosAdapter() *TezosAdapter {
	return &TezosAdapter{
		blocks: make(map[uint64]*TezosBlock),
		bakers: make(map[string]*TezosBaker),
	}
}

func (a *TezosAdapter) ChainID() ChainID                   { return idTezos }
func (a *TezosAdapter) ChainName() string                  { return "Tezos" }
func (a *TezosAdapter) VerificationMode() VerificationMode { return ModeLightClient }
func (a *TezosAdapter) GetBlockTime() time.Duration        { return 15 * time.Second }
func (a *TezosAdapter) GetRequiredConfirmations() uint64   { return 2 }

func (a *TezosAdapter) Initialize(config *ChainConfig) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.config = config
	a.initialized = true
	return nil
}

func (a *TezosAdapter) VerifyBlockHeader(ctx context.Context, header *BlockHeader) error {
	if header.ChainID != idTezos {
		return ErrChainNotSupported
	}
	return nil
}

func (a *TezosAdapter) VerifyTransaction(ctx context.Context, proof *TxInclusionProof) error { return nil }
func (a *TezosAdapter) VerifyMessage(ctx context.Context, msg *CrossChainMessage) error      { return nil }
func (a *TezosAdapter) VerifyEvent(ctx context.Context, event *ChainEvent) error            { return nil }

func (a *TezosAdapter) GetLatestFinalizedBlock(ctx context.Context) (uint64, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return a.latestFinalized, nil
}

func (a *TezosAdapter) IsFinalized(ctx context.Context, level uint64) (bool, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	return level <= a.latestFinalized, nil
}

func (a *TezosAdapter) GetValidatorSet(ctx context.Context) (*ValidatorSet, error) { return nil, nil }

func (a *TezosAdapter) Close() error {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.blocks = nil
	a.bakers = nil
	a.initialized = false
	return nil
}

// (Lux/Quasar C-Chain is handled natively by the Lux node — no foreign-chain adapter needed.)
