package node_test

import (
	"testing"

	edgenode "iop/apps/edge/internal/node"
	"iop/packages/go/config"
)

func TestLoadFromConfig_Success(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "beta", Token: "token-beta"},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}

	rec, ok := store.FindByToken("token-beta")
	if !ok {
		t.Fatal("expected record for token-beta")
	}
	if rec.Alias != "beta" {
		t.Fatalf("expected alias %q, got %q", "beta", rec.Alias)
	}
	if rec.ID == "" {
		t.Fatal("expected non-empty ID")
	}

	if _, ok := store.FindByToken("missing"); ok {
		t.Fatal("expected missing token lookup to fail")
	}
}

func TestLoadFromConfig_DuplicateToken(t *testing.T) {
	_, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "alpha", Token: "token"},
		{Alias: "beta", Token: "token"},
	})
	if err == nil {
		t.Fatal("expected duplicate token error")
	}
}

func TestLoadFromConfig_DuplicateAlias(t *testing.T) {
	_, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "alpha", Token: "token-alpha"},
		{Alias: "alpha", Token: "token-beta"},
	})
	if err == nil {
		t.Fatal("expected duplicate alias error")
	}
}

func TestLoadFromConfig_EmptyToken(t *testing.T) {
	_, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "alpha"},
	})
	if err == nil {
		t.Fatal("expected empty token error")
	}
}

func TestLoadFromConfig_ExplicitID(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{ID: "my-custom-id", Alias: "alpha", Token: "token-alpha"},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}

	rec, ok := store.FindByToken("token-alpha")
	if !ok {
		t.Fatal("expected record for token-alpha")
	}
	if rec.ID != "my-custom-id" {
		t.Fatalf("expected id %q, got %q", "my-custom-id", rec.ID)
	}
}

func TestLoadFromConfig_AutoID(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "alpha", Token: "token-alpha"},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}

	rec, ok := store.FindByToken("token-alpha")
	if !ok {
		t.Fatal("expected record for token-alpha")
	}
	if rec.ID == "" {
		t.Fatal("expected auto-generated non-empty ID")
	}
	if rec.ID == "node-alpha" {
		t.Fatal("expected UUID, not alias-derived ID")
	}
}

func TestLoadFromConfig_DuplicateID(t *testing.T) {
	_, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{ID: "node-dup", Alias: "alpha", Token: "token-alpha"},
		{ID: "node-dup", Alias: "beta", Token: "token-beta"},
	})
	if err == nil {
		t.Fatal("expected duplicate id error")
	}
}

func TestLoadFromConfigAgentKind(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "explicit", Token: "token-explicit", AgentKind: config.AgentKindGenericNode},
		{Alias: "plain", Token: "token-plain"},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}

	explicitRec, ok := store.FindByToken("token-explicit")
	if !ok {
		t.Fatal("expected record for token-explicit")
	}
	if explicitRec.AgentKind != config.AgentKindGenericNode {
		t.Fatalf("expected agent_kind=%q, got %q", config.AgentKindGenericNode, explicitRec.AgentKind)
	}

	plainRec, ok := store.FindByToken("token-plain")
	if !ok {
		t.Fatal("expected record for token-plain")
	}
	if plainRec.AgentKind != config.AgentKindGenericNode {
		t.Fatalf("expected default agent_kind=%q, got %q", config.AgentKindGenericNode, plainRec.AgentKind)
	}
}

func TestLoadFromConfig_DuplicateTokenWithAgentKind(t *testing.T) {
	_, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "alpha", Token: "token", AgentKind: config.AgentKindGenericNode},
		{Alias: "beta", Token: "token", AgentKind: config.AgentKindGenericNode},
	})
	if err == nil {
		t.Fatal("expected duplicate token error regardless of agent kind")
	}
}

func TestLoadFromConfig_LegacyOllamaInPayload(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{
			ID:    "node-ollama",
			Alias: "ollama-node",
			Token: "token-ollama",
			Adapters: config.AdaptersConf{
				Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://127.0.0.1:11434"},
			},
		},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}
	rec, ok := store.FindByToken("token-ollama")
	if !ok {
		t.Fatal("expected record for token-ollama")
	}
	payload, err := edgenode.BuildConfigPayload(rec)
	if err != nil {
		t.Fatalf("build config payload: %v", err)
	}
	var found bool
	for _, a := range payload.GetAdapters() {
		if a.GetType() == "ollama" && a.GetOllama().GetBaseUrl() == "http://127.0.0.1:11434" {
			found = true
		}
	}
	if !found {
		t.Fatalf("expected ollama adapter in payload with correct base_url, got %v", payload.GetAdapters())
	}
}

func TestLoadFromConfig_LegacyVllmInPayload(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{
			ID:    "node-vllm",
			Alias: "vllm-node",
			Token: "token-vllm",
			Adapters: config.AdaptersConf{
				Vllm: config.VllmConf{Enabled: true, Endpoint: "http://127.0.0.1:8000"},
			},
		},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}
	rec, ok := store.FindByToken("token-vllm")
	if !ok {
		t.Fatal("expected record for token-vllm")
	}
	payload, err := edgenode.BuildConfigPayload(rec)
	if err != nil {
		t.Fatalf("build config payload: %v", err)
	}
	var found bool
	for _, a := range payload.GetAdapters() {
		if a.GetType() == "vllm" && a.GetVllm().GetEndpoint() == "http://127.0.0.1:8000" {
			found = true
		}
	}
	if !found {
		t.Fatalf("expected vllm adapter in payload with correct endpoint, got %v", payload.GetAdapters())
	}
}

func TestLoadFromConfig_AutoIDUnique(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{Alias: "alpha", Token: "token-alpha"},
		{Alias: "beta", Token: "token-beta"},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}

	recA, ok := store.FindByToken("token-alpha")
	if !ok {
		t.Fatal("expected record for token-alpha")
	}
	recB, ok := store.FindByToken("token-beta")
	if !ok {
		t.Fatal("expected record for token-beta")
	}
	if recA.ID == recB.ID {
		t.Fatalf("expected unique IDs, both are %q", recA.ID)
	}
}

func TestLoadFromConfig_LegacyOpenAICompatInPayload(t *testing.T) {
	store, err := edgenode.LoadFromConfig([]config.NodeDefinition{
		{
			ID:    "node-oai",
			Alias: "oai-node",
			Token: "token-oai",
			Adapters: config.AdaptersConf{
				OpenAICompat: config.OpenAICompatConf{
					Enabled:  true,
					Provider: "lemonade",
					Endpoint: "http://127.0.0.1:13305",
					Headers:  map[string]string{"authorization": "Bearer token"},
				},
			},
		},
	})
	if err != nil {
		t.Fatalf("load from config: %v", err)
	}
	rec, ok := store.FindByToken("token-oai")
	if !ok {
		t.Fatal("expected record for token-oai")
	}
	payload, err := edgenode.BuildConfigPayload(rec)
	if err != nil {
		t.Fatalf("build config payload: %v", err)
	}
	var found bool
	for _, a := range payload.GetAdapters() {
		if a.GetType() == "openai_compat" {
			oai := a.GetOpenaiCompat()
			if oai != nil && oai.GetProvider() == "lemonade" && oai.GetEndpoint() == "http://127.0.0.1:13305" && oai.GetHeaders()["authorization"] == "Bearer token" {
				found = true
			}
		}
	}
	if !found {
		t.Fatalf("expected openai_compat adapter in payload with correct config, got %v", payload.GetAdapters())
	}
}
