package query

import (
	"context"
	"errors"
	"testing"

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

	"github.com/tidbcloud/observability/o11ydiagnosis/pkg/utils/metacache"
)

type stubMetaCache struct {
	lastCluster string
	lastTenant  string
	info        *metacache.MetaInfo
	err         error
}

func (s *stubMetaCache) GetMetaInfo(_ context.Context, _, _, tenant, _, cluster string, _, _ bool) (*metacache.MetaInfo, error) {
	s.lastTenant = tenant
	s.lastCluster = cluster
	return s.info, s.err
}

func TestLooksLikeO11yClusterID(t *testing.T) {
	assert.True(t, looksLikeO11yClusterID("019b23f6-ffc9-731d-be49-eb8f9e651855"))
	assert.True(t, looksLikeO11yClusterID("34750647-d0ba-4e59-9ffe-cd719c1c6af6"))
	assert.False(t, looksLikeO11yClusterID("10000701911982538398"))
	assert.False(t, looksLikeO11yClusterID("k8s-infra"))
	assert.False(t, looksLikeO11yClusterID(""))
}

func TestResolveSlowlogsClusterID(t *testing.T) {
	t.Run("nil meta leaves application id", func(t *testing.T) {
		s := &Service{cfg: Config{Region: "us-west-2"}}
		scope := Scope{"org": ScopeEq("t1"), "cluster": ScopeEq("10000701911982538398")}
		require.NoError(t, s.resolveSlowlogsClusterID(context.Background(), clusterHeader{}, scope))
		v, _ := scope.GetString("cluster")
		assert.Equal(t, "10000701911982538398", v)
	})

	t.Run("uuid passthrough", func(t *testing.T) {
		stub := &stubMetaCache{info: &metacache.MetaInfo{O11yID: "should-not-call"}}
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: stub}
		uuid := "019b23f6-ffc9-731d-be49-eb8f9e651855"
		scope := Scope{"org": ScopeEq("t1"), "cluster": ScopeEq(uuid)}
		require.NoError(t, s.resolveSlowlogsClusterID(context.Background(), clusterHeader{TenantID: "t1"}, scope))
		v, _ := scope.GetString("cluster")
		assert.Equal(t, uuid, v)
		assert.Empty(t, stub.lastCluster)
	})

	t.Run("application id resolved", func(t *testing.T) {
		stub := &stubMetaCache{info: &metacache.MetaInfo{O11yID: "019b23f6-ffc9-731d-be49-eb8f9e651855"}}
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: stub}
		scope := Scope{"org": ScopeEq("1372813089188151296"), "cluster": ScopeEq("10000701911982538398")}
		hdr := clusterHeader{TenantID: "ignored", Env: "prod", DeployType: "dedicated", Region: "us-east-1"}
		require.NoError(t, s.resolveSlowlogsClusterID(context.Background(), hdr, scope))
		v, _ := scope.GetString("cluster")
		assert.Equal(t, "019b23f6-ffc9-731d-be49-eb8f9e651855", v)
		assert.Equal(t, "10000701911982538398", stub.lastCluster)
		assert.Equal(t, "1372813089188151296", stub.lastTenant)
	})

	t.Run("missing tenant", func(t *testing.T) {
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: &stubMetaCache{}}
		scope := Scope{"cluster": ScopeEq("10000701911982538398")}
		err := s.resolveSlowlogsClusterID(context.Background(), clusterHeader{}, scope)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "x-org-id")
	})

	t.Run("meta miss", func(t *testing.T) {
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: &stubMetaCache{info: nil}}
		scope := Scope{"org": ScopeEq("t1"), "cluster": ScopeEq("10000701911982538398")}
		err := s.resolveSlowlogsClusterID(context.Background(), clusterHeader{TenantID: "t1"}, scope)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "not found")
	})

	t.Run("meta error", func(t *testing.T) {
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: &stubMetaCache{err: errors.New("boom")}}
		scope := Scope{"org": ScopeEq("t1"), "cluster": ScopeEq("10000701911982538398")}
		err := s.resolveSlowlogsClusterID(context.Background(), clusterHeader{TenantID: "t1"}, scope)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "boom")
	})

	t.Run("uuid array passthrough from scope/list", func(t *testing.T) {
		stub := &stubMetaCache{info: &metacache.MetaInfo{O11yID: "should-not-call"}}
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: stub}
		u1 := "019b23f6-ffc9-731d-be49-eb8f9e651855"
		u2 := "34750647-d0ba-4e59-9ffe-cd719c1c6af6"
		scope := Scope{"org": ScopeEq("t1"), "cluster": ScopeIn(u1, u2)}
		require.NoError(t, s.resolveSlowlogsClusterID(context.Background(), clusterHeader{TenantID: "t1"}, scope))
		assert.Equal(t, []string{u1, u2}, scope["cluster"].in)
		assert.Empty(t, stub.lastCluster)
	})

	t.Run("application id array resolved", func(t *testing.T) {
		stub := &stubMetaCache{info: &metacache.MetaInfo{O11yID: "019b23f6-ffc9-731d-be49-eb8f9e651855"}}
		s := &Service{cfg: Config{Region: "us-west-2"}, meta: stub}
		scope := Scope{"org": ScopeEq("t1"), "cluster": ScopeIn("10000701911982538398", "019b23f6-ffc9-731d-be49-eb8f9e651855")}
		require.NoError(t, s.resolveSlowlogsClusterID(context.Background(), clusterHeader{TenantID: "t1"}, scope))
		assert.Equal(t, []string{
			"019b23f6-ffc9-731d-be49-eb8f9e651855",
			"019b23f6-ffc9-731d-be49-eb8f9e651855",
		}, scope["cluster"].in)
		assert.Equal(t, "10000701911982538398", stub.lastCluster)
	})
}
