package event

import "time"

// DomainEvent is the base interface for all domain events.
type DomainEvent interface {
	// EventName returns the fully-qualified event name.
	EventName() string
	// OccurredAt returns the timestamp when the event was created.
	OccurredAt() time.Time
}

// BlockIndexedEvent is published when a new block has been successfully indexed.
type BlockIndexedEvent struct {
	Height    int64     `json:"height"`
	Hash      string    `json:"hash"`
	TxCount   int       `json:"txCount"`
	Timestamp time.Time `json:"timestamp"`
	occurredAt time.Time
}

// NewBlockIndexedEvent creates a new BlockIndexedEvent.
func NewBlockIndexedEvent(height int64, hash string, txCount int, blockTime time.Time) *BlockIndexedEvent {
	return &BlockIndexedEvent{
		Height:     height,
		Hash:       hash,
		TxCount:    txCount,
		Timestamp:  blockTime,
		occurredAt: time.Now(),
	}
}

// EventName returns the event name.
func (e *BlockIndexedEvent) EventName() string {
	return "chain.block.indexed"
}

// OccurredAt returns when the event was created.
func (e *BlockIndexedEvent) OccurredAt() time.Time {
	return e.occurredAt
}

// TransactionIndexedEvent is published when a transaction has been indexed.
type TransactionIndexedEvent struct {
	TxHash      string    `json:"txHash"`
	BlockHeight int64     `json:"blockHeight"`
	From        string    `json:"from"`
	To          string    `json:"to"`
	Amount      string    `json:"amount"`
	Status      string    `json:"status"`
	occurredAt  time.Time
}

// NewTransactionIndexedEvent creates a new TransactionIndexedEvent.
func NewTransactionIndexedEvent(txHash string, blockHeight int64, from, to, amount, status string) *TransactionIndexedEvent {
	return &TransactionIndexedEvent{
		TxHash:      txHash,
		BlockHeight: blockHeight,
		From:        from,
		To:          to,
		Amount:      amount,
		Status:      status,
		occurredAt:  time.Now(),
	}
}

// EventName returns the event name.
func (e *TransactionIndexedEvent) EventName() string {
	return "chain.transaction.indexed"
}

// OccurredAt returns when the event was created.
func (e *TransactionIndexedEvent) OccurredAt() time.Time {
	return e.occurredAt
}

// EventPublisher defines the contract for publishing domain events.
// Infrastructure layer (e.g. Kafka) provides the concrete implementation.
type EventPublisher interface {
	// Publish sends a domain event to the event bus.
	Publish(event DomainEvent) error
}
