package anthropic

import (
	"encoding/json"
	"errors"
	"testing"

	"nex/backend/internal/conversion"
	"nex/backend/internal/conversion/canonical"

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

func TestAdapter_ProtocolName(t *testing.T) {
	a := NewAdapter()
	assert.Equal(t, "anthropic", a.ProtocolName())
}

func TestAdapter_ProtocolVersion(t *testing.T) {
	a := NewAdapter()
	assert.Equal(t, "2023-06-01", a.ProtocolVersion())
}

func TestAdapter_SupportsPassthrough(t *testing.T) {
	a := NewAdapter()
	assert.True(t, a.SupportsPassthrough())
}

func TestAdapter_DetectInterfaceType(t *testing.T) {
	a := NewAdapter()

	tests := []struct {
		name     string
		path     string
		expected conversion.InterfaceType
	}{
		{"聊天消息", "/v1/messages", conversion.InterfaceTypeChat},
		{"模型列表", "/v1/models", conversion.InterfaceTypeModels},
		{"模型详情", "/v1/models/claude-3", conversion.InterfaceTypeModelInfo},
		{"未知路径", "/v1/unknown", conversion.InterfaceTypePassthrough},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := a.DetectInterfaceType(tt.path)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestAdapter_APIReferenceNativePaths(t *testing.T) {
	a := NewAdapter()

	// docs/api_reference/anthropic defines messages and models under /v1.
	tests := []struct {
		path     string
		expected conversion.InterfaceType
	}{
		{"/v1/messages", conversion.InterfaceTypeChat},
		{"/v1/models", conversion.InterfaceTypeModels},
		{"/v1/models/claude-sonnet-4-5", conversion.InterfaceTypeModelInfo},
		{"/messages", conversion.InterfaceTypePassthrough},
		{"/models", conversion.InterfaceTypePassthrough},
	}

	for _, tt := range tests {
		t.Run(tt.path, func(t *testing.T) {
			assert.Equal(t, tt.expected, a.DetectInterfaceType(tt.path))
		})
	}
}

func TestAdapter_BuildUrl(t *testing.T) {
	a := NewAdapter()

	tests := []struct {
		name          string
		nativePath    string
		interfaceType conversion.InterfaceType
		expected      string
	}{
		{"聊天", "/v1/messages", conversion.InterfaceTypeChat, "/v1/messages"},
		{"模型", "/v1/models", conversion.InterfaceTypeModels, "/v1/models"},
		{"默认透传", "/v1/other", conversion.InterfaceTypePassthrough, "/v1/other"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := a.BuildUrl(tt.nativePath, tt.interfaceType)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestAdapter_BuildHeaders_Basic(t *testing.T) {
	a := NewAdapter()
	provider := conversion.NewTargetProvider("https://api.anthropic.com", "sk-ant-test", "claude-3")

	headers := a.BuildHeaders(provider)
	assert.Equal(t, "sk-ant-test", headers["x-api-key"])
	assert.Equal(t, "2023-06-01", headers["anthropic-version"])
	assert.Equal(t, "application/json", headers["Content-Type"])
}

func TestAdapter_BuildHeaders_CustomVersion(t *testing.T) {
	a := NewAdapter()
	provider := conversion.NewTargetProvider("https://api.anthropic.com", "sk-ant-test", "claude-3")
	provider.AdapterConfig["anthropic_version"] = "2024-01-01"

	headers := a.BuildHeaders(provider)
	assert.Equal(t, "2024-01-01", headers["anthropic-version"])
}

func TestAdapter_BuildHeaders_AnthropicBeta(t *testing.T) {
	a := NewAdapter()
	provider := conversion.NewTargetProvider("https://api.anthropic.com", "sk-ant-test", "claude-3")
	provider.AdapterConfig["anthropic_beta"] = []string{"prompt-caching-2024-07-31", "max-tokens-3-5-sonnet-2024-07-15"}

	headers := a.BuildHeaders(provider)
	assert.Equal(t, "prompt-caching-2024-07-31,max-tokens-3-5-sonnet-2024-07-15", headers["anthropic-beta"])
}

func TestAdapter_SupportsInterface(t *testing.T) {
	a := NewAdapter()

	tests := []struct {
		name          string
		interfaceType conversion.InterfaceType
		expected      bool
	}{
		{"聊天", conversion.InterfaceTypeChat, true},
		{"模型", conversion.InterfaceTypeModels, true},
		{"模型详情", conversion.InterfaceTypeModelInfo, true},
		{"嵌入", conversion.InterfaceTypeEmbeddings, false},
		{"重排序", conversion.InterfaceTypeRerank, false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := a.SupportsInterface(tt.interfaceType)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestAdapter_EncodeError(t *testing.T) {
	a := NewAdapter()
	convErr := conversion.NewConversionError(conversion.ErrorCodeInvalidInput, "参数无效")

	body, statusCode := a.EncodeError(convErr)
	require.Equal(t, 500, statusCode)

	var resp ErrorResponse
	require.NoError(t, json.Unmarshal(body, &resp))
	assert.Equal(t, "error", resp.Type)
	assert.Equal(t, "INVALID_INPUT", resp.Error.Type)
	assert.Equal(t, "参数无效", resp.Error.Message)
}

func TestAdapter_UnsupportedEmbedding(t *testing.T) {
	a := NewAdapter()

	t.Run("解码嵌入请求", func(t *testing.T) {
		_, err := a.DecodeEmbeddingRequest([]byte(`{}`))
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})

	t.Run("编码嵌入请求", func(t *testing.T) {
		provider := conversion.NewTargetProvider("https://api.anthropic.com", "key", "claude-3")
		_, err := a.EncodeEmbeddingRequest(&canonical.CanonicalEmbeddingRequest{}, provider)
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.True(t, errors.As(err, &convErr))
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})

	t.Run("解码嵌入响应", func(t *testing.T) {
		_, err := a.DecodeEmbeddingResponse([]byte(`{}`))
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})

	t.Run("编码嵌入响应", func(t *testing.T) {
		_, err := a.EncodeEmbeddingResponse(&canonical.CanonicalEmbeddingResponse{})
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})
}

func TestAdapter_UnsupportedRerank(t *testing.T) {
	a := NewAdapter()

	t.Run("解码重排序请求", func(t *testing.T) {
		_, err := a.DecodeRerankRequest([]byte(`{}`))
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})

	t.Run("编码重排序请求", func(t *testing.T) {
		provider := conversion.NewTargetProvider("https://api.anthropic.com", "key", "claude-3")
		_, err := a.EncodeRerankRequest(&canonical.CanonicalRerankRequest{}, provider)
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})

	t.Run("解码重排序响应", func(t *testing.T) {
		_, err := a.DecodeRerankResponse([]byte(`{}`))
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})

	t.Run("编码重排序响应", func(t *testing.T) {
		_, err := a.EncodeRerankResponse(&canonical.CanonicalRerankResponse{})
		require.Error(t, err)
		var convErr *conversion.ConversionError
		require.ErrorAs(t, err, &convErr)
		assert.Equal(t, conversion.ErrorCodeInterfaceNotSupported, convErr.Code)
	})
}
