// 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 (
	"fmt"
	"net"
	"os"
	"path/filepath"

	coreio "dappco.re/go/core/io"
	coreerr "dappco.re/go/core/log"

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

const defaultChainSeed = "seeds.lthn.io:36942"

// AddChainCommands registers the `chain` command group on a Cobra root.
//
// Example:
//
//	cli.WithCommands("chain", blockchain.AddChainCommands)
//
// The command group owns the explorer and sync subcommands, so the
// command path documents the node features directly.
func AddChainCommands(root *cobra.Command) {
	var (
		chainDataDir    string
		seedPeerAddress string
		useTestnet      bool
	)

	chainCmd := &cobra.Command{
		Use:   "chain",
		Short: "Lethean blockchain node",
		Long:  "Manage the Lethean blockchain — sync, explore, and mine.",
	}

	chainCmd.PersistentFlags().StringVar(&chainDataDir, "data-dir", defaultChainDataDirPath(), "blockchain data directory")
	chainCmd.PersistentFlags().StringVar(&seedPeerAddress, "seed", defaultChainSeed, "seed peer address (host:port)")
	chainCmd.PersistentFlags().BoolVar(&useTestnet, "testnet", false, "use testnet")

	chainCmd.AddCommand(
		newChainExplorerCommand(&chainDataDir, &seedPeerAddress, &useTestnet),
		newChainSyncCommand(&chainDataDir, &seedPeerAddress, &useTestnet),
	)

	root.AddCommand(chainCmd)
}

func chainConfigForSeed(useTestnet bool, seedPeerAddress string) (config.ChainConfig, []config.HardFork, string) {
	if useTestnet {
		if seedPeerAddress == defaultChainSeed {
			seedPeerAddress = "localhost:46942"
		}
		return config.Testnet, config.TestnetForks, seedPeerAddress
	}
	return config.Mainnet, config.MainnetForks, seedPeerAddress
}

func defaultChainDataDirPath() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ".lethean"
	}
	return filepath.Join(home, ".lethean", "chain")
}

func ensureChainDataDirExists(dataDir string) error {
	if err := coreio.Local.EnsureDir(dataDir); err != nil {
		return coreerr.E("ensureChainDataDirExists", "create data dir", err)
	}
	return nil
}

func validateChainOptions(chainDataDir, seedPeerAddress string) error {
	if chainDataDir == "" {
		return coreerr.E("validateChainOptions", "data dir is required", nil)
	}
	if seedPeerAddress == "" {
		return coreerr.E("validateChainOptions", "seed is required", nil)
	}
	if _, _, err := net.SplitHostPort(seedPeerAddress); err != nil {
		return coreerr.E("validateChainOptions", fmt.Sprintf("seed %q must be host:port", seedPeerAddress), err)
	}
	return nil
}
