// 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 (
	"testing"

	"github.com/spf13/cobra"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestAddChainCommands_Good_RegistersParent(t *testing.T) {
	root := &cobra.Command{Use: "test"}
	AddChainCommands(root)

	chainCmd, _, err := root.Find([]string{"chain"})
	require.NoError(t, err)
	assert.Equal(t, "chain", chainCmd.Name())
}

func TestAddChainCommands_Good_HasSubcommands(t *testing.T) {
	root := &cobra.Command{Use: "test"}
	AddChainCommands(root)

	chainCmd, _, _ := root.Find([]string{"chain"})

	var names []string
	for _, sub := range chainCmd.Commands() {
		names = append(names, sub.Name())
	}
	assert.Contains(t, names, "explorer")
	assert.Contains(t, names, "sync")
}

func TestAddChainCommands_Good_PersistentFlags(t *testing.T) {
	root := &cobra.Command{Use: "test"}
	AddChainCommands(root)

	chainCmd, _, _ := root.Find([]string{"chain"})

	assert.NotNil(t, chainCmd.PersistentFlags().Lookup("data-dir"))
	assert.NotNil(t, chainCmd.PersistentFlags().Lookup("seed"))
	assert.NotNil(t, chainCmd.PersistentFlags().Lookup("testnet"))
}

func TestValidateChainOptions_Good(t *testing.T) {
	err := validateChainOptions("/tmp/lethean", "seed.example:36942")
	require.NoError(t, err)
}

func TestValidateChainOptions_Bad(t *testing.T) {
	tests := []struct {
		name    string
		dataDir string
		seed    string
		want    string
	}{
		{name: "missing data dir", dataDir: "", seed: "seed.example:36942", want: "data dir is required"},
		{name: "missing seed", dataDir: "/tmp/lethean", seed: "", want: "seed is required"},
		{name: "malformed seed", dataDir: "/tmp/lethean", seed: "seed.example", want: "must be host:port"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := validateChainOptions(tt.dataDir, tt.seed)
			require.Error(t, err)
			assert.Contains(t, err.Error(), tt.want)
		})
	}
}

func TestChainSyncCommand_BadMutuallyExclusiveFlags(t *testing.T) {
	dataDir := t.TempDir()
	seed := "seed.example:36942"
	testnet := false

	cmd := newChainSyncCommand(&dataDir, &seed, &testnet)
	cmd.SetArgs([]string{"--daemon", "--stop"})

	err := cmd.Execute()
	require.Error(t, err)
	assert.Contains(t, err.Error(), "cannot be combined")
}

func TestChainSyncCommand_BadArgsRejected(t *testing.T) {
	dataDir := t.TempDir()
	seed := "seed.example:36942"
	testnet := false

	cmd := newChainSyncCommand(&dataDir, &seed, &testnet)
	cmd.SetArgs([]string{"extra"})

	err := cmd.Execute()
	require.Error(t, err)
	assert.Contains(t, err.Error(), "unknown command")
}

func TestChainExplorerCommand_BadSeedRejected(t *testing.T) {
	dataDir := t.TempDir()
	seed := "bad-seed"
	testnet := false

	cmd := newChainExplorerCommand(&dataDir, &seed, &testnet)
	cmd.SetArgs(nil)

	err := cmd.Execute()
	require.Error(t, err)
	assert.Contains(t, err.Error(), "must be host:port")
}
