package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"strconv"
	"syscall"

	"github.com/ethereum/go-ethereum/ethclient"
	pgconfig "github.com/explorer/backend/libs/go-pgconfig"
	"github.com/explorer/backend/indexer/listener"
	"github.com/explorer/backend/indexer/processor"
	"github.com/jackc/pgx/v5/pgxpool"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Load configuration (reusable lib: libs/go-pgconfig)
	dbConfig := pgconfig.LoadDatabaseConfig()
	poolConfig, err := dbConfig.PoolConfig()
	if err != nil {
		log.Fatalf("Failed to create pool config: %v", err)
	}

	// Connect to database
	db, err := pgxpool.NewWithConfig(ctx, poolConfig)
	if err != nil {
		log.Fatalf("Failed to connect to database: %v", err)
	}
	defer db.Close()

	// Connect to RPC
	rpcURL := os.Getenv("RPC_URL")
	if rpcURL == "" {
		rpcURL = "http://localhost:8545"
	}

	wsURL := os.Getenv("WS_URL")
	chainID := 138
	if envChainID := os.Getenv("CHAIN_ID"); envChainID != "" {
		if id, err := strconv.Atoi(envChainID); err == nil {
			chainID = id
		}
	}

	client, err := ethclient.Dial(rpcURL)
	if err != nil {
		log.Fatalf("Failed to connect to RPC: %v", err)
	}
	defer client.Close()

	// Create block listener
	blockListener, err := listener.NewBlockListener(rpcURL, wsURL, int64(chainID))
	if err != nil {
		log.Fatalf("Failed to create block listener: %v", err)
	}
	defer blockListener.Stop()

	// Create block processor
	blockProcessor := processor.NewBlockProcessor(db, client, chainID)

	// Start listening
	if err := blockListener.Start(); err != nil {
		log.Fatalf("Failed to start block listener: %v", err)
	}

	// Process blocks
	go func() {
		for block := range blockListener.GetBlockChannel() {
			if err := blockProcessor.ProcessBlock(ctx, block); err != nil {
				log.Printf("Failed to process block %d: %v", block.Number().Int64(), err)
			} else {
				log.Printf("Processed block %d", block.Number().Int64())
			}
		}
	}()

	// Wait for interrupt
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
	<-sigChan

	log.Println("Shutting down...")
}
