// Copyright (c) 2017-2026 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// SPDX-License-Identifier: EUPL-1.2

package blockchain

import (
	"context"
	"os"
	"os/signal"
	"path/filepath"
	"sync"

	corelog "dappco.re/go/core/log"

	cli "dappco.re/go/core/cli/pkg/cli"
	store "dappco.re/go/core/store"

	"dappco.re/go/core/blockchain/chain"
	"dappco.re/go/core/blockchain/tui"
	"github.com/spf13/cobra"
)

// newChainExplorerCommand builds the interactive `chain explorer` command.
//
// Example:
//
//	chain explorer --data-dir ~/.lethean/chain
//
// Use it alongside `AddChainCommands` to expose the TUI node view.
func newChainExplorerCommand(chainDataDir, seedPeerAddress *string, useTestnet *bool) *cobra.Command {
	return &cobra.Command{
		Use:   "explorer",
		Short: "TUI block explorer",
		Long:  "Interactive terminal block explorer with live sync status.",
		Args:  cobra.NoArgs,
		PreRunE: func(cmd *cobra.Command, args []string) error {
			return validateChainOptions(*chainDataDir, *seedPeerAddress)
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			return runChainExplorer(*chainDataDir, *seedPeerAddress, *useTestnet)
		},
	}
}

func runChainExplorer(chainDataDir, seedPeerAddress string, useTestnet bool) error {
	if err := ensureChainDataDirExists(chainDataDir); err != nil {
		return err
	}

	dbPath := filepath.Join(chainDataDir, "chain.db")
	chainStore, err := store.New(dbPath)
	if err != nil {
		return corelog.E("runChainExplorer", "open store", err)
	}
	defer chainStore.Close()

	blockchain := chain.New(chainStore)
	chainConfig, hardForks, resolvedSeed := chainConfigForSeed(useTestnet, seedPeerAddress)

	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
	defer cancel()

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		runChainSyncLoop(ctx, blockchain, &chainConfig, hardForks, resolvedSeed)
	}()

	node := tui.NewNode(blockchain)
	status := tui.NewStatusModel(node)
	explorer := tui.NewExplorerModel(blockchain)
	hints := tui.NewKeyHintsModel()

	frame := cli.NewFrame("HCF")
	frame.Header(status)
	frame.Content(explorer)
	frame.Footer(hints)
	corelog.Info("running chain explorer", "data_dir", chainDataDir, "seed", resolvedSeed, "testnet", useTestnet)
	frame.Run()

	cancel()  // Signal the sync loop to stop.
	wg.Wait() // Wait for it before closing store.
	return nil
}
