package runtime

import (
	"encoding/base64"
	"encoding/json"
	"io"
	"log/slog"
	"testing"
	"time"

	"aigateway.local/core/internal/gateway"
	"aigateway.local/core/internal/provider"
	provideropenai "aigateway.local/core/internal/provider/openai"
)

func TestBuildRuntimeAdapter(t *testing.T) {
	key := base64.StdEncoding.EncodeToString(make([]byte, 32))
	cipher, err := provider.NewCredentialCipher(key, 1)
	if err != nil {
		t.Fatal(err)
	}
	encrypted, version, err := cipher.Encrypt([]byte(`{"api_key":"upstream-secret"}`))
	if err != nil {
		t.Fatal(err)
	}
	fallback, _ := provideropenai.New("https://fallback.example", "")
	resolver := NewResolver(nil, cipher, fallback, time.Second, slog.New(slog.NewTextHandler(io.Discard, nil)))
	resolved, defaultProvider, err := resolver.build(provider.Record{
		Code: "primary", Adapter: "openai-compatible", BaseURL: "https://upstream.example/v1",
		EncryptedCredentials: encrypted, CredentialKEKVersion: version,
		Capabilities: []string{"chat", "models"}, Config: json.RawMessage(`{"default":true}`), Revision: 3,
	})
	if err != nil {
		t.Fatal(err)
	}
	if resolved.Code != "primary" || resolved.Revision != 3 || !resolved.Capabilities[provider.CapabilityChat] || !defaultProvider {
		t.Fatalf("unexpected resolved adapter: %#v, default=%v", resolved, defaultProvider)
	}
}

func TestModelRouteUsesConditionsPriorityAndExplicitProvider(t *testing.T) {
	first, _ := provideropenai.New("https://first.example", "")
	second, _ := provideropenai.New("https://second.example", "")
	resolver := &Resolver{}
	resolver.snapshot.Store(&snapshot{
		adapters: map[string]gateway.ResolvedAdapter{
			"first": {Code: "first", Adapter: first}, "second": {Code: "second", Adapter: second},
		},
		routes: map[string][]compiledRoute{"public-chat": {
			{providerCode: "first", targetModel: "model-a", weight: 100, priority: 10},
			{providerCode: "second", targetModel: "model-b", weight: 100, priority: 20, conditions: routeConditions{Endpoints: []string{"/v1/chat/completions"}}},
		}},
		knownModels: map[string]bool{"public-chat": true},
	})
	result, err := resolver.ResolveModelRoute(gateway.ModelRouteQuery{Model: "public-chat", Endpoint: "/v1/chat/completions", Seed: "request-1"})
	if err != nil || !result.Matched || result.Code != "second" || result.TargetModel != "model-b" {
		t.Fatalf("unexpected priority route: %#v %v", result, err)
	}
	result, err = resolver.ResolveModelRoute(gateway.ModelRouteQuery{ProviderCode: "first", Model: "public-chat", Endpoint: "/v1/chat/completions", Seed: "request-1"})
	if err != nil || !result.Matched || result.Code != "first" {
		t.Fatalf("explicit provider was not respected: %#v %v", result, err)
	}
	result, err = resolver.ResolveModelRoute(gateway.ModelRouteQuery{ProviderCode: "second", Model: "public-chat", Endpoint: "/v1/embeddings", Seed: "request-1"})
	if err != nil || result.Matched || !result.Known {
		t.Fatalf("known alias with unmatched conditions must fail closed: %#v %v", result, err)
	}
}

func TestResolverStartsWithEnvironmentFallback(t *testing.T) {
	fallback, _ := provideropenai.New("https://fallback.example", "")
	resolver := NewResolver(nil, nil, fallback, time.Second, slog.New(slog.NewTextHandler(io.Discard, nil)))
	resolved, err := resolver.Resolve("")
	if err != nil || resolved.Code != "environment" {
		t.Fatalf("fallback resolve: %#v %v", resolved, err)
	}
	if _, err := resolver.Resolve("missing"); err == nil {
		t.Fatal("unknown provider must be rejected")
	}
}
