package providers

import (
	"net/http"
	"testing"
	"time"
)

func TestBuildKimiChatRequestStripsPrefixAndAppliesThinking(t *testing.T) {
	base := NewHTTPProvider("kimi", "token", kimiCompatBaseURL, "kimi-k2.5", false, "oauth", 5*time.Second, nil)
	body := buildKimiChatRequest(base, []Message{{Role: "user", Content: "hi"}}, nil, "kimi-k2.5(high)", nil, false)

	if got := body["model"]; got != "k2.5" {
		t.Fatalf("model = %#v, want k2.5", got)
	}
	if got := body["reasoning_effort"]; got != "high" {
		t.Fatalf("reasoning_effort = %#v, want high", got)
	}
}

func TestBuildKimiChatRequestDisablesThinking(t *testing.T) {
	base := NewHTTPProvider("kimi", "token", kimiCompatBaseURL, "kimi-k2.5", false, "oauth", 5*time.Second, nil)
	body := buildKimiChatRequest(base, []Message{{Role: "user", Content: "hi"}}, nil, "kimi-k2.5(none)", nil, false)

	thinking, _ := body["thinking"].(map[string]interface{})
	if got := thinking["type"]; got != "disabled" {
		t.Fatalf("thinking.type = %#v, want disabled", got)
	}
}

func TestNormalizeKimiToolMessagesBackfillsToolCallID(t *testing.T) {
	body := map[string]interface{}{
		"messages": []map[string]interface{}{
			{
				"role": "assistant",
				"tool_calls": []map[string]interface{}{
					{"id": "call_1"},
				},
				"content": "thinking content",
			},
			{
				"role":    "tool",
				"content": "tool result",
			},
		},
	}

	normalizeKimiToolMessages(body)

	msgs := body["messages"].([]map[string]interface{})
	if got := msgs[1]["tool_call_id"]; got != "call_1" {
		t.Fatalf("tool_call_id = %#v, want call_1", got)
	}
	if got := msgs[0]["reasoning_content"]; got != "thinking content" {
		t.Fatalf("reasoning_content = %#v, want fallback content", got)
	}
}

func TestNormalizeKimiToolMessagesPromotesCallID(t *testing.T) {
	body := map[string]interface{}{
		"messages": []map[string]interface{}{
			{
				"role":    "tool",
				"call_id": "call_2",
			},
		},
	}

	normalizeKimiToolMessages(body)

	msgs := body["messages"].([]map[string]interface{})
	if got := msgs[0]["tool_call_id"]; got != "call_2" {
		t.Fatalf("tool_call_id = %#v, want call_2", got)
	}
}

func TestApplyAttemptProviderHeadersKimiUsesResolvedDeviceFields(t *testing.T) {
	req, err := http.NewRequest(http.MethodPost, kimiCompatBaseURL+"/chat/completions", nil)
	if err != nil {
		t.Fatalf("new request: %v", err)
	}
	provider := &HTTPProvider{
		oauth: &oauthManager{cfg: oauthConfig{Provider: defaultKimiOAuthProvider}},
	}
	attempt := authAttempt{
		kind:  "oauth",
		token: "kimi-token",
		session: &oauthSession{
			DeviceID: "device-123",
		},
	}

	applyAttemptProviderHeaders(req, attempt, provider, true)

	if got := req.Header.Get("X-Msh-Device-Id"); got != "device-123" {
		t.Fatalf("X-Msh-Device-Id = %q, want device-123", got)
	}
	if got := req.Header.Get("X-Msh-Device-Model"); got != kimiDeviceModel() {
		t.Fatalf("X-Msh-Device-Model = %q, want %q", got, kimiDeviceModel())
	}
	if got := req.Header.Get("X-Msh-Device-Name"); got == "" {
		t.Fatal("expected X-Msh-Device-Name to be set")
	}
}

func TestKimiHookUsesSessionResourceURL(t *testing.T) {
	hooks := kimiProviderHooks{}
	base := NewHTTPProvider("kimi", "token", kimiCompatBaseURL, "kimi-k2.5", false, "oauth", 5*time.Second, nil)
	got := hooks.endpoint(base, authAttempt{
		kind: "oauth",
		session: &oauthSession{
			ResourceURL: "https://api.kimi.com/coding/v1",
		},
	}, "/chat/completions")
	if got != "https://api.kimi.com/coding/v1/chat/completions" {
		t.Fatalf("endpoint = %q", got)
	}
}

func TestNormalizeKimiResourceURL(t *testing.T) {
	tests := []struct {
		in   string
		want string
	}{
		{in: "https://api.kimi.com/coding", want: "https://api.kimi.com/coding/v1"},
		{in: "api.kimi.com/coding", want: "https://api.kimi.com/coding/v1"},
		{in: "https://api.kimi.com/coding/v1", want: "https://api.kimi.com/coding/v1"},
	}
	for _, tt := range tests {
		if got := normalizeKimiResourceURL(tt.in); got != tt.want {
			t.Fatalf("normalizeKimiResourceURL(%q) = %q, want %q", tt.in, got, tt.want)
		}
	}
}

func TestKimiProviderCountTokens(t *testing.T) {
	provider := NewKimiProvider("kimi", "token", kimiCompatBaseURL, "kimi-k2.5", false, "api_key", 5*time.Second, nil)
	usage, err := provider.CountTokens(t.Context(), []Message{{Role: "user", Content: "hello kimi"}}, nil, "kimi-k2.5", nil)
	if err != nil {
		t.Fatalf("CountTokens error: %v", err)
	}
	if usage == nil || usage.PromptTokens <= 0 || usage.TotalTokens != usage.PromptTokens {
		t.Fatalf("usage = %#v, want positive prompt-only count", usage)
	}
}

func TestBuildKimiChatRequestSupportsNumericAutoAndDisable(t *testing.T) {
	base := NewHTTPProvider("kimi", "token", kimiCompatBaseURL, "kimi-k2.5", false, "oauth", 5*time.Second, nil)
	autoBody := buildKimiChatRequest(base, []Message{{Role: "user", Content: "hi"}}, nil, "kimi-k2.5(-1)", nil, false)
	if got := autoBody["reasoning_effort"]; got != "auto" {
		t.Fatalf("reasoning_effort = %#v, want auto", got)
	}
	disableBody := buildKimiChatRequest(base, []Message{{Role: "user", Content: "hi"}}, nil, "kimi-k2.5(0)", nil, false)
	thinking, _ := disableBody["thinking"].(map[string]interface{})
	if got := thinking["type"]; got != "disabled" {
		t.Fatalf("thinking.type = %#v, want disabled", got)
	}
}
